【问题标题】:warning: initializer element is not constant [duplicate]警告:初始化元素不是常量[重复]
【发布时间】:2013-11-04 05:16:58
【问题描述】:

所有,

我有下面的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

我不知道具体是什么原因,请您帮帮我。谢谢

【问题讨论】:

    标签: c


    【解决方案1】:

    在 C89/90 中,所有用大括号括起来的初始化程序都必须是常量。在 C99 及更高版本中,对象的大括号括起来的初始值设定项具有静态存储持续时间必须是常量。

    这就是您的情况:sdp_header 是一个具有静态存储持续时间的数组,这意味着您只能在 {} 之间使用常量。

    除了strlen 之外,您的所有初始化程序似乎都是常量。函数调用不会产生常量。在您的具体情况下,您可以将 strlen 替换为 sizeof

    #define SDP_FILL_STRUCT(a,b) {#a, b, sizeof b - 1, sdp_##a}
    

    但它只有在 b 代表文字字符串时才有效(在您的示例中就是这种情况)。

    此外,您的最后一个初始化程序要么错误,要么具有误导性,具体取决于您的意图。 valparse_key 应该在最后一个元素中的值是多少?如果你想要空字符串,那么它应该是

    { "", "", 0, NULL }
    

    如果你想要空指针,那么它应该是

    { NULL, NULL, 0, NULL }
    

    { 0, 0, 0, 0 }
    

    甚至只是

    { 0 }
    

    您当前的'\0' 将用作空指针常量,但指定空指针常量是一种误导和奇怪的方式。

    为什么你将0 转为void * 作为函数指针成员也不清楚。为什么?只需写NULL 或普通0。无需演员。如果你想要一个演员,至少把它转换成正确的类型。 void * 哪里来的?

    【讨论】:

    • @icepack:上次我检查时,C 不允许{}。 C++ 允许{}
    • 不知道。它适用于 C99 之前的版本。
    • @icepack: 哪个编译器?
    • @icepack:哦,好的。这是一个非标准的 GCC 扩展。如果您在严格标准模式下运行 GCC(例如,在 -std=c90-std=c99 下),这将触发诊断消息。
    【解决方案2】:

    这是因为两个问题:

    const char* val;
    const char* parse_key;
    
    #define SDP_FILL_STRUCT(a,b) {#a, b, strlen(b), sdp_##a} //strlen(b)
    

    问题一:

    strlen 在编译时不会被评估.. 所以编译器会抱怨.. strlen 只会在运行代码时被评估。

    请注意,某些编译器可能能够将其优化为编译时常量,但这并不能假设您被允许做您正在尝试做的事情。

    问题2:(来源:https://stackoverflow.com/a/3025106/1253932

    在 C 语言中,术语“常量”是指文字常量(如 1、'a'、0xFF 等)和枚举成员。常量限定的对象(任何类型)在 C 语言术语中不是常量。它们不能用于具有静态存储持续时间的对象的初始化程序,无论其类型如何。

    例如,这不是一个常数

    const int C = 5; /* `C` is not a constant in C */
    

    上面的 C 在 C++ 中是常量,但在 C 中不是常量。所以,如果你尝试这样做

    static int j = C; /* ERROR */
    

    你会得到同样的错误:试图用一个非常量初始化一个静态对象。

    【讨论】:

      猜你喜欢
      • 2013-12-08
      • 1970-01-01
      • 2015-07-21
      • 1970-01-01
      • 1970-01-01
      • 2020-03-27
      • 2013-09-24
      • 1970-01-01
      相关资源
      最近更新 更多