2

このコードにより、コンパイル エラー「エラー: 'p' が別の型で再定義されています」が発生します。

void fun() {
    printf("fun");
}
void (*p)();
p = &fun;

しかし、 に変更すれば
void (*p)(); p = &fun;
void (*p)() = &funすべて OK です。


void (*p)(); p = &fun;とはどう違い
void (*p)() = &funますか?

4

4 に答える 4

3

グローバル スコープで任意の割り当てを実行することはできません。試す:

void fun() {
    printf("fun");
}

void (*p)();

int main(void) {
 p = &fun;
 return 0;
}

void (*p)() = &fun;変数を作成して初期化しているため、機能します。初期化はグローバル スコープで許可されます。void (*p)(); p = &fun;初期化されていない変数を作成し、それに値を割り当てます。割り当ては初期化とは異なる方法で処理され、一部の関数内で実行する必要があります。

于 2012-07-15T14:36:46.983 に答える
2
void (*p)();   // This is a declaration

void (*p)() = &fun;  // This is also a declaration

宣言です。

p = &fun;  // This is a statement

は声明です。ステートメントは宣言ではありません (宣言はステートメントではありません)。

ファイル スコープでステートメントを使用することはできません。C では、ブロック スコープでのみステートメントを使用できます。

于 2012-07-15T14:42:20.243 に答える
2

グローバル スコープでは、宣言と関数定義のみが有効です。割り当てはありません。

違いは、int n = 1;初期化を伴う宣言であるのに対してn = 1;、代入であることです。前者はグローバル スコープで有効ですが、後者は有効ではありません。関数ポインタについても同様です。

原則として、割り当てよりも初期化を常に優先する必要があり、それで問題が解決します。

void fun() { /* ... */ }

void (*p)() = &fun;  // declaration, definition and initialization of "p"
于 2012-07-15T14:42:56.310 に答える
1

前の 3 つの回答は質問に答えていません。「p = &fun;」を示している場合は正しくありません。課題です。

実際、コンパイラは「p = &fun;」を解釈しようとしています。"p" は宣言子、"&fun" は初期化子、"p = &fun" は init-declarator (C 仕様の正式な文法) を形成します。

これを宣言として解釈すると、宣言に含める必要がある型はデフォルトで int になるため (従来の理由から)、コンパイラは基本的にこれを「int p = &fun;」、つまり p の定義と見なします。p は以前に関数へのポインタとして定義されていたため、コンパイラは p を別の型で再定義していると警告します。

言語文法の専門家向け: これがどのようにして形式文法の宣言になるのか、私にはわかりません。translation-unit は external-declaration に展開され、external-declaration は宣言に展開され、宣言は「declaration-specifiers init-declarator-list[opt];」に展開されます。(C 標準の 6.7 あたり)。宣言指定子には、ストレージ クラス指定子、タイプ指定子、タイプ修飾子、または関数指定子に含まれるキーワードの少なくとも 1 つが必要なようです。そのようなキーワードはソースに表示されないため、これは宣言ではありません。コンパイラが 1999 年標準より前の文法で構文解析していると思われるため、これは従来の動作です。それにもかかわらず、エラー メッセージは、コンパイラが 2 つの定義を認識したことを明確に示しています。

于 2012-07-15T15:06:29.397 に答える