有些情況下,該代碼可以出現兩個上下文 - 在函數內部和函數外。
- 該代碼在一個上下文中有效 - 在函數內。
- 該代碼在其他上下文中無效 - 在函數外部。
這可能說明了編譯器是否接受代碼的不同觀點。
鑑於代碼:
char* str[] = { "abc" };
struct test { char* str_in_struct; } tests[] = { { str[0] } };
void somefunc(void)
{
char* str[] = { "abc" };
struct test tests[] = { { str[0] } };
}
彙編(與在MacOS X 10.6.7 GCC 4.1.2)收率:
$ /usr/bin/gcc -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -c xx.c
xx.c:2: error: initializer element is not constant
xx.c:2: error: (near initialization for ‘tests[0].str_in_struct’)
xx.c:2: warning: missing initializer
xx.c:2: warning: (near initialization for ‘tests[0].str_in_struct’)
xx.c:5: warning: no previous prototype for ‘somefunc’
xx.c: In function ‘somefunc’:
xx.c:7: warning: unused variable ‘tests’
$
爲線5和7是相當準確的警告;第2行的錯誤也是準確的。
有什麼麻煩?
基本上,str[0]
需要鏈接器不能做(或不需要做)的計算。
在這個版本的代碼,test2
是確定的,但tests
和test3
不是:
struct test { char* str_in_struct; };
char *str[] = { "abc" };
char pqr[] = "abc";
char *xyz = "abc";
struct test tests[] = { { str[0] } };
struct test test2[] = { { pqr } };
struct test test3[] = { { xyz } };
void somefunc(void)
{
char* str[] = { "abc" };
struct test tests[] = { { str[0] } };
}
您可以參考數組名外部初始化。您不能引用數組元素,也不能引用指針變量的值。
複述評論/問題:
[It] seems though that if char str4[][4] = { "abc", "d" };
, then struct test { char* str_in_struct; } test4[] = { { str4[1] } };
is valid. So then, you can refer to array elements, but only if their size is known?
我還沒有完全正確表徵它 - 你說得對。我已經給出了部分答案,但不是完整的答案。基本上,'out of function'初始值設定項中的表達式必須是常量。它不像「只有大小已知」那麼簡單。問題在於初始化程序中的表達式是否可以在沒有從內存中讀取值的情況下進行計算。
使用str[0]
(原始版本),您必須讀取存儲在str[0]
;與xyz
類似。使用pqr
版本和str4
版本(注意與註釋相比額外的4
),值(地址)pqr
或str4[1]
可由連接器計算而不讀取存儲在那裏的值。
在C99標準,§6.7.8初始化說:
¶4 All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
§6。6個常量表達式表示:
¶2 A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be.
和:
¶7 More latitude is permitted for constant expressions in initializers. Such a constant expression shall be, or evaluate to, one of the following:
— an arithmetic constant expression,
— a null pointer constant,
— an address constant, or
— an address constant for an object type plus or minus an integer constant expression.
¶8 An arithmetic constant expression shall have arithmetic type and shall only have operands that are integer constants, floating constants, enumeration constants, character constants, and sizeof
expressions. Cast operators in an arithmetic constant expression shall only convert arithmetic types to arithmetic types, except as part of an operand to a sizeof
operator whose result is an integer constant.
¶9 An address constant is a null pointer, a pointer to an lvalue designating an object of static storage duration, or a pointer to a function designator; it shall be created explicitly using the unary &
operator or an integer constant cast to pointer type, or implicitly by the use of an expression of array or function type. The array-subscript []
and member-access .
and ->
operators, the address &
and indirection *
unary operators, and pointer casts may be used in the creation of an address constant, but the value of an object shall not be accessed by use of these operators.
注意預選賽「,但對象的值不應通過使用訪問這些運營商。這與我之前在回答擴展中寫到的內容一致。特別是,str4[1]
的值只需要數組str4
的地址常量加上一個整數常量表達式(項目符號列表中的最後一個備選項)。同樣,pqr
是一個地址常量(項目符號列表中的第三個替代項)。但str[0]
和xyz
初始值設定項必須訪問不允許的對象值。
你有什麼問題? gcc對此非常滿意(與-Wall -Wextra)。語義是否與你期望的不同? – 2011-04-30 11:40:01
gcc說:main.c:6:錯誤:初始化元素不是常量 main.c:6:錯誤:(初始化接近'tests [0] .str_in_struct') main.c:6:warning:missing initializer main.c:6:warning:('test [0] .str_in_struct'初始化接近) – rid 2011-04-30 13:20:16