C - 无法初始化struct“错误:初始化元素不是常量”

时间:2018-01-04 21:03:34

标签: c struct

我的问题相当简单。我试图在我的main函数中初始化struct但是我收到以下错误:

$ gcc main2.c -o main2
main2.c: In function ‘main’:
main2.c:39:28: error: initializer element is not constant
             .smth.array = (mylib_B_t)
                            ^
main2.c:39:28: note: (near initialization for ‘C.smth.array’)

我尝试了多种不同的方式,但似乎没有任何效果。 有人能告诉我我做错了什么吗? 以下是有问题的代码:

#include <stdio.h>

typedef struct mylib_A_t mylib_A_t;
typedef struct mylib_B_t mylib_B_t;
typedef struct mylib_C_t mylib_C_t;

typedef enum
{
    TYPE_A = 0,
    TYPE_B  = -1
} lib_type_t;

struct mylib_A_t
{
    lib_type_t type;
    int d;
};

struct mylib_B_t
{
     int c;
     const mylib_A_t *size;
 };

struct mylib_C_t
{
    union
    {
        int b;
        mylib_B_t array;
     } smth;
};

int main (int argc, char * argv[])
{
    static const mylib_C_t C=
    {

        .smth.array = (mylib_B_t)
        {
            .c = 66,
            .size = &(mylib_A_t)
                   {
                       .type = TYPE_A,
                       .d = 0
                   }
        }
    };
    return 0;
}

1 个答案:

答案 0 :(得分:4)

具有静态存储持续时间的对象的初始化程序必须由常量表达式组成。你的代码以两种方式与之相悖,都与复合文字的使用有关。

这是mylib_A_t类型的复合文字:

(mylib_A_t)
{
    .type = TYPE_A,
    .d = 0
}

。它表示类型为mylib_A_t对象,即使其初始值是根据常量定义的,它也不是&#34;常量&#34;也不是&#34;常数表达&#34;因为标准使用该术语。

您似乎也不会意识到虽然它们具有相似的语法,但初始化表达式(包括嵌套的初始化程序)是 not 赋值语句,并且它们不遵循相同的规则。特别是,该标准规定了

  

初始化程序中的常量表达式允许更多的宽容度[与其他地方相对]。   这样的常数表达式应该是或者评估为其中之一   以下内容:

     
      
  • 算术常量表达式
  •   
  • 一个空指针常量,
  •   
  • 地址常量,或
  •   
  • 完整对象类型的地址常量加上或减去整数常量表达式。
  •   

C2011, 6.6/7

您可以像这样编写初始化:

int main (int argc, char *argv[]) {
    // You cannot avoid a declaration of such a static-duration object if
    // you want to use a pointer to such an object in the initializer of C:
    static const mylib_A_t A = {
        .type = TYPE_A,
        .d = 0
    };

    static const mylib_C_t C = {
        // The initializer for .smth.array must be (just) a brace-enclosed
        // initializer list, NOT a compound literal
        .smth.array = {
            .c = 66,
            // &A is an address constant; the pointer expression in your
            // original code is not
            .size = &A
        }
    };
    return 0;
}

在那里,所有初始化程序都是根据该上下文中允许的常量表达式的类型编写的。