1

このコードは、ステートメント1にコメントした後は正常に機能します。ステートメント2は、ある程度のガベージ値を示しますが、少なくとも実行されます。関数として呼び出されていない場合、引数のprintfがどのように値を与えるのかわかりませんか?

#include<stdio.h>

int main()
{
    int printf = 123;    // statement one
    printf ("%d", printf); // statement two  
    return 0;
}
4

2 に答える 2

3

括弧のない関数名は値を返しません-関数のアドレスに評価されます(つまり、タイプの関数ポインターですsize_t (*)(const char *, ...))。基本的に、これは、CPUがへの呼び出しに遭遇するたびに命令間をジャンプするアドレスprintf()です。

ちなみに、私が正しく思い出せば、関数の名前への割り当ては未定義の動作であるため、%dフォーマット指定子を使用してポインターを出力します-を使用する必要があります

printf("%p", (void *)printf);

また、関数ポインタ宣言し、それらに別の関数のアドレスを割り当てて、それらをうまく呼び出すことができます。

size_t (*my_printf)(const char *, ...) = printf;
my_printf("This actually called printf!\n");

printf("my_printf: %p\n", (void *)my_printf);
printf("original printf: %p\n", (void *)printf);

最後の2つのステートメントは、同じアドレスを出力します。

編集:厳密に言えば、上記の「解決策」でさえ、関数ポインターがデータポインター型にキャストできることを標準が保証していないため、非標準です。これは基本的に、関数のアドレスを出力する方法がないことを意味しますが、ほとんどのシステムでは、キャストはvoid * 明らかに機能します。

于 2012-10-06T13:45:01.393 に答える
3

ステートメント2では、識別子printfが関数に渡されると、それは関数ポインター(関数へのポインター)でprintfあり、ガベージ値printfは、次の形式を使用してこのアドレスを出力しようとした結果です::%dコンパイラの警告が表示されるはずですを使用してポインタを出力する場合%d

于 2012-10-06T13:45:02.093 に答える