相关疑难解决方法(0)

尝试使用const初始化变量时,错误"初始化元素不是常量"

我在以下程序的第6行(初始化my_foo到foo_init)时收到错误,我不确定我理解为什么.

typedef struct foo_t {
    int a, b, c;
} foo_t;

const foo_t foo_init = { 1, 2, 3 };
foo_t my_foo = foo_init;

int main()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

请记住,这是我正在研究的大型多文件项目的简化版本.目标是在目标文件中有一个常量,多个文件可用于初始化状态结构.由于它是一个资源有限的嵌入式目标,并且结构不是那么小,我不想要源的多个副本.我不想使用:

#define foo_init { 1, 2, 3 }
Run Code Online (Sandbox Code Playgroud)

我也在尝试编写可移植代码,所以我需要一个有效的C89或C99解决方案.

这是否与目标文件中的ORG有关?初始化变量进入一个ORG并通过复制第二个ORG的内容进行初始化?

也许我只需要改变我的策略,并在启动时使用初始化功能完成所有副本.除非有其他想法吗?

c initialization

175
推荐指数
4
解决办法
22万
查看次数

索引字符串文字是初始化常量表达式吗?

以下代码尝试在两个不同的常量上下文中对字符串文字使用数组索引:

static char x = "abcx"[3];

_Static_assert ("abcx"[3] == 'x', "...");
Run Code Online (Sandbox Code Playgroud)

根据Compiler Explorer的判断,工具供应商之间存在明确的共识,即不允许在第二种情况下执行此操作,因为第二种情况明确要求使用整数常量表达式。但是,它们似乎在第一个上下文方面有所不同,第一个上下文只是初始化程序中使用的算术常数表达式。GCC和Clang是允许这样做的实现而脱颖而出。

就其本身而言,这并不有趣,因为在6.6的第10段中,C11 / C18确实表示“实现可以接受其他形式的常量表达式”。但是,在这种情况下脱颖而出是因为:

  • GCC和Clang都默默地接受了这一点-pedantic(是的,编译器签发并不意味着代码符合要求)。构建代码很有意义,因为它的含义很简单,但是如果他们认为这不符合要求,我会期望发出警告,并且他们可以识别(他们认为)它是否符合要求,因为...

  • 对于这两个编译器,行为最近都发生了变化 -Clang一直在此之前引发错误,直到3.8,而GCC之前一直在引发错误直到8.0。这些版本分别于2016年和2018年发布。这表明更改是有意的,但我还没有找到详细介绍这两个编译器的发行说明。

行为改变的时机使它看起来像与C18有关,但是6.6的措词似乎没有改变。对整数常量表达式的限制仍然严格(如第二行继续显示错误),第9段的措词似乎与C11中的相同,特别是继续说:“对象的值不应为C。通过使用这些运算符可以访问”(wrt []和朋友)。

通过阅读标准,第一个上下文是否是有效的初始化常量(不包括第10段)?我在哪里可能找到GCC / Clang变更的理由?

c language-lawyer constant-expression c11 c17

11
推荐指数
1
解决办法
140
查看次数

为什么在 gcc 上接受 const 限定变量作为初始值设定项?

在最新版本的 gcc(或 clang)中编译此代码时 -std=c17 -pedantic-errors -Wall -Wextra

static const int y = 1;
static int x = y;
Run Code Online (Sandbox Code Playgroud)

然后我没有收到编译器诊断消息,即使我相当确定这不是有效的 C 而是约束违规。我们可以通过查看C17 6.7.9/4来证明它是不符合的:

约束
...
具有静态或线程存储持续时间的对象的初始值设定项中的所有表达式都应为常量表达式或字符串文字。

然后是关于常量表达式的定义,在这种情况下是整数常量表达式(6.6):

整数常量表达式应具有整数类型,并且只能具有整数常量、枚举常量、字符常量、结果为整数常量的 sizeof 表达式、_Alignof 表达式和作为强制转换的直接操作数的浮点常量的操作数。

最后是关于整数常量的定义(6.4.4.1/2):

整数常量以数字开头,但没有句点或指数部分。它可能有一个指定其基础的前缀和一个指定其类型的后缀。

因此,const int变量不是整数常量,也不是整数常量表达式。因此不是有效的初始化程序。这之前已经讨论过(例如这里),我认为已经确定这是不合格的。但是,我的问题是:

为什么 gcc 即使在严格模式下也选择不合规?

clang 显然一直不合规,但 gcc 从 7.3 版的合规变为 8.0 及更高版本的不合规。即使在没有-pedantic-errors.

似乎已经对这条消息做出了某种积极的、有意识的决定。为什么在 gcc 中完全删除它,为什么在严格模式下编译时不保留它-std=c17 -pedantic-errors

c gcc initializer static-initialization

6
推荐指数
1
解决办法
204
查看次数