2011-04-30 72 views
3

有沒有辦法在C中做這樣的事情?我可以靜態初始化C中一個結構中的char *嗎?

char* str[] = { "abc" }; 
struct test { char* str_in_struct; } tests[] = { 
    { str[0] } 
}; 

如果我嘗試編譯此,GCC說:

main.c:6: error: initializer element is not constant 
main.c:6: error: (near initialization for ‘tests[0].str_in_struct’) 
main.c:6: warning: missing initializer 
main.c:6: warning: (near initialization for ‘tests[0].str_in_struct’) 
+0

你有什麼問題? gcc對此非常滿意(與-Wall -Wextra)。語義是否與你期望的不同? – 2011-04-30 11:40:01

+0

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

回答

4

有些情況下,該代碼可以出現兩個上下文 - 在函數內部和函數外。

  • 該代碼在一個上下文中有效 - 在函數內。
  • 該代碼在其他上下文中無效 - 在函數外部。

這可能說明了編譯器是否接受代碼的不同觀點。

鑑於代碼:

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是確定的,但teststest3不是:

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),值(地址)pqrstr4[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初始值設定項必須訪問不允許的對象值。

+0

似乎如果'char str [] [4] = {「abc」,「d」};',那麼' struct test {char * str_in_struct; } tests [] = {{str [1]}}'是有效的。那麼,你可以引用數組元素,但只有當它們的大小已知時纔可以。 – rid 2011-04-30 16:24:28

相關問題