2011-04-30 40 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

相关问题