所有
我在编译时有以下C代码,
static struct
{
const char* val;
const char* parse_key;
int len; //parse key length
void (*parse_routine) (const char* after, rtsp_sdp_t* response);
} sdp_header[] =
{
#define SDP_FILL_STRUCT(a,b) {#a, b, strlen(b), sdp_##a}
SDP_FILL_STRUCT(attr_control, "a=control:"),
SDP_FILL_STRUCT(attr_framerate,"a=framerate:"),
SDP_FILL_STRUCT(attr_range, "a=range:"),
{'\0', '\0', 0, (void*)0},
};
为什么它会发出以下错误:
:330: warning: initializer element is not constant
:330: warning: (near initialization for 'sdp_header[0]')
:331: warning: initializer element is not constant
:331: warning: (near initialization for 'sdp_header[1]')
:332: warning: initializer element is not constant
:332: warning: (near initialization for 'sdp_header[2]')
:333: warning: initializer element is not constant
我不知道到底是什么原因,你能不能给我一些帮助。谢谢
答案 0 :(得分:5)
在C89 / 90中,所有支撑封闭的初始化器都必须是常数。在C99及更高版本中,带有静态存储持续时间的对象的大括号内置初始值设定项必须是常量。
这就是您的情况:sdp_header
是一个具有静态存储持续时间的数组,这意味着您只能使用{}
之间的常量。
除了strlen
之外,所有初始值设定项似乎都是常量。函数调用不会产生常量。在您的具体情况下,您可以将strlen
替换为sizeof
#define SDP_FILL_STRUCT(a,b) {#a, b, sizeof b - 1, sdp_##a}
但仅当b
代表文字字符串时才会起作用(在您的示例中就是这种情况)。
此外,根据您的意图,您的上一个初始化程序错误或具有误导性。 val
和parse_key
应该在最后一个元素中的值是多少?如果你想要空字符串,那么它应该是
{ "", "", 0, NULL }
如果你想要空指针,那么它应该是
{ NULL, NULL, 0, NULL }
或
{ 0, 0, 0, 0 }
甚至仅仅是
{ 0 }
您当前的'\0'
将作为空指针常量工作,但指定空指针常量是一种误导性和奇怪的方式。
为什么你为函数指针成员设置0
到void *
也是不清楚的。为什么?只需撰写NULL
或简单0
即可。没有必要的演员。如果你想要一个演员,至少把它投到合适的类型。 void *
来自哪里?
答案 1 :(得分:2)
因为有两个问题:
const char* val;
const char* parse_key;
#define SDP_FILL_STRUCT(a,b) {#a, b, strlen(b), sdp_##a} //strlen(b)
问题1:
编译时未评估 strlen
..因此编译器会抱怨.. strlen
仅在运行代码时进行评估。
请注意,某些编译器可能能够将其优化为编译时常量,但这并不能使您认为您可以执行您正在尝试执行的操作。
问题2:(来源:https://stackoverflow.com/a/3025106/1253932)
在C语言中,术语“常量”是指文字常量(如1,'a',0xFF等)和枚举成员。 Const限定对象(任何类型)不是C语言术语中的常量。它们不能用于具有静态存储持续时间的对象的初始值设定项,无论其类型如何。
例如,这不是常数
const int C = 5; /* `C` is not a constant in C */
上面的C在C ++中是一个常量,但它在C中不是常数。所以,如果你尝试做
static int j = C; /* ERROR */
您将得到相同的错误:尝试使用非常量初始化静态对象。