たとえば、次の 2 つのステートメントに違いはありますか。
extern char a[];
extern char a[4];
(別のソース ファイル内の) a の実際の定義が
char a[5];
だがしかし
char a[4];
たとえば、次の 2 つのステートメントに違いはありますか。
extern char a[];
extern char a[4];
(別のソース ファイル内の) a の実際の定義が
char a[5];
だがしかし
char a[4];
extern int a[]
a
サイズが指定されていないの配列であると宣言しint
、「不完全型」と見なされます (C.11 §6.7.6.2 ¶4)。不完全型とは、そのサイズを決定するのに十分な情報がないものです (C.11 §6.2.5 ¶1)。の使用extern
は、名前に「外部リンケージ」があることを意味します (C.11 §6.2.2 ¶4)。外部リンケージを持つ同じ名前へのプログラム内のすべての参照は、同じオブジェクトを参照します (C.11 §6.2.2 ¶2)。
を持っていてextern int a[4]
、他の場所で として定義されているint a[5]
場合、これは未定義の動作につながります (C.11 §6.2.7 ¶2):
同じオブジェクトまたは関数を参照するすべての宣言は、互換性のある型を持つ必要があります。それ以外の場合、動作は undefinedです。
以下:
extern char a[ ]; // (1)
... 意味: 「a と呼ばれる文字の配列をどこかに探しに行ってください。存在します。」
extern char a[ c ]; // (2), where c is some constant.
... 意味: 「a と呼ばれるサイズ ( char * c ) の文字の配列をどこかに探しに行きます。存在します。」.
両方の宣言の実際の例:配列のサイズがわかっている場合は、2 番目の宣言を行う必要があります。配列が VLA の場合、最初の宣言を使用して宣言する必要があります。