C &引用;初始值设定项元素不是常量;将对象定义为函数的静态成员时

C &引用;初始值设定项元素不是常量;将对象定义为函数的静态成员时,c,constants,static-initialization,C,Constants,Static Initialization,以下代码编译时没有任何投诉: struct s { const int a; }; static const struct s *s = &(const struct s) { .a = 5 }; int main(void) { (void) s; return 0; } 但是,如果我们将s的定义移动到main的主体,即: struct s { const int a; }; int main(void) { static con

以下代码编译时没有任何投诉:

struct s {
    const int a;
};

static const struct s *s = &(const struct s) {
    .a = 5
};

int main(void) {
    (void) s;
    return 0;
}
但是,如果我们将
s
的定义移动到
main
的主体,即:

struct s {
    const int a;
};

int main(void) {
    static const struct s *s = &(const struct s) {
        .a = 5
    };
    (void) s;
    return 0;
}
我们得到一个错误:

error: initializer element is not constant
    static const struct s* s = &(const struct s) {
                               ^
既然在这两种情况下,我们都处理静态(即编译时)初始化,为什么第二个用例是非法的? 在函数的上下文中是否有任何方法使其合法

(我已经用GCC 7.3.0和clang 6.0.0对此进行了检查,他们都将此报告为错误)

根据C 2018 6.6(“常量表达式”)7:

初始值设定项中的常量表达式允许更大的自由度。此类常量表达式应为或计算为以下之一:……地址常量,或

根据6.6.9:

地址常量是空指针、指向指定静态存储持续时间对象的左值的指针或指向函数指示符的指针

然后,在6.5.2.5(“复合文字”)5中,我们有:

…如果复合文字出现在函数体之外,则对象具有静态存储持续时间;否则,它具有与封闭块关联的自动存储持续时间


因此,在第一种情况下,复合文字是具有静态存储持续时间的对象,指向它的指针是地址常量。在第二种情况下,复合文字是具有自动存储持续时间的对象,并且指向它的指针不是地址常量。

在第二种情况下为复合文字创建的对象具有自动存储类。有没有办法在第二种情况下强制执行静态存储持续时间?只需执行
static const struct s temp_variable={…}
static const struct s*s=&temp\u variable
@EricPostpischil:我想你的意思是:
static const struct s*s=&foo
@machine\u 1:是的,谢谢,但是KamilCuk的评论可以涵盖它。