提问人:user16217248 提问时间:10/16/2023 更新时间:10/16/2023 访问量:104
为什么 GCC 不能在结构初始值设定项中以 sizeof 作为条件的三元中处理复合文本的编译时计算?
Why can GCC not handle compile-time evaluation of compound literal in a ternary with sizeof as a condition inside a struct initializer?
问:
以下代码:
struct Int {
int i;
};
const struct Int i = {sizeof(int) ? (int){1} : 0};
结果:
initializer 元素不是常量
即使这些语句在文件范围内,因此复合文本也应被视为常量。
但是,如果:
- 我改用 Clang;或
- 我用 0 替换 ;或
sizeof(int)
- 我用 1 替换 ;或
(int){1}
- 表达式用于直接初始化结构成员,而不是结构成员,如下所示:
int
int
int i = sizeof(int) ? (int){1} : 0;
代码可以很好地编译。
这引发了几个问题:
- 标准 C 是否允许使用与三元一起使用的语句将一个全局结构变量成员初始化为 2 个值之一,其中至少一个是复合文本,所有这些都在编译时完成?
sizeof()
- 如果满足上述所有 3 个要求,为什么 GCC 会引发错误,但如果只满足任何 2 或 1 个,代码就可以正常编译?
答:
在 C23 之前,关于整数常量表达式的组成,在 gcc 和 clang 错误报告等中有很多争论。Clang总是有“任何事物及其母亲都是恒定的表达”的行为,而GCC则更加严格,直到后来的版本,GCC突然翻转了行为,尽管这里的标准已经很久没有改变过了。所有这些都是由 C17(和早期标准)6.6 §10 中一个无益的、浑浊的段落引起的:
实现可以接受其他形式的常量表达式。
这是第 6.6 章中唯一留有解释空间并允许像您这样的代码的部分。这意味着整数常量表达式在 gcc 和 clang 中都有不稳定的支持,代码使用常量表达式的“异国情调”形式,例如复合文字,或者根本不是不可移植的。市场上的大多数其他编译器都会给出有关不合格 C 的诊断信息。const int x = some_other_const;
在 C17 之前,整数常量表达式定义如下 (C17 6.6 §6):
整数常量表达式应具有整数类型,并且只能具有整数常量、枚举常量、字符常量、结果为整数的表达式的操作数 常量、表达式和浮动常量,它们是强制转换的直接操作数。
sizeof
_Alignof
在即将到来的 C23 中,此更改(C23 N3096 草案 6.6. §8 强调我的):
整数常量表达式应具有整数类型,并且只能具有作为整数常量的操作数、整数类型的命名和复合文字常量、字符常量、...
其中“命名常量”是一个新术语,除其他外,它涵盖了以下内容:
使用 storage-class 说明符声明,并具有对象类型,
constexpr
因此,C23 将允许复合文字,我们也可以便携式地这样做(constexpr int){1}
constexpr int x = 1; const int y=x;
评论
struct
上一个:对类型进行编译时操作
下一个:编译时间字节序相关表达式?
评论
(int){1}
对我来说看起来很奇怪,但是,C有一些奇怪的怪癖。(int){1}
int
1
int
(int){1}
int
1
int
(int){1}