Gan*_*nil 16 c gcc struct compound-literals
GCC在c99/gnu99模式中使用复合文字进行静态结构初始化时,我遇到了一个奇怪的行为.
显然这很好:
struct Test
{
int a;
};
static struct Test tt = {1}; /* 1 */
Run Code Online (Sandbox Code Playgroud)
但是,这不是:
static struct Test tt = (struct Test) {1}; /* 2 */
Run Code Online (Sandbox Code Playgroud)
这会触发以下错误:
初始化元素不是常量
这也无济于事:
static struct Test tt = (const struct Test) {1}; /* 3 */
Run Code Online (Sandbox Code Playgroud)
我确实理解静态结构的初始化值应该是编译时常量.但我不明白为什么这个最简单的初始化表达式不再被认为是常量?这是由标准定义的吗?
我问的原因是我在gnu90模式下遇到了一些用GCC编写的遗留代码,它使用了这种复合文字结构进行静态结构初始化(2).显然,这是当时的GNU扩展,后来被C99采用.
现在,它导致在与成功编译的代码GNU90不能与没有被编译C99,甚至也不是GNU99.
他们为什么要这样对我?
Sha*_*our 10
这是一个gcc bug( HT到cremno),错误报告说:
我相信我们应该允许使用复合文字来初始化具有静态存储持续时间的对象,即使在gnu99/gnu11中也是如此.[...](但与 - 警告警告.)
我们可以从gcc文档中看到复合文字,应该支持具有静态存储持续时间的对象的初始化作为扩展:
作为GNU扩展,GCC允许通过复合文字初始化具有静态存储持续时间的对象(这在ISO C99中是不可能的,因为初始化器不是常量).
这是固定的gcc 5.2.所以,在gcc 5.2你使用-pedantic旗帜时只会看到它的警告只会出现这个警告,没有抱怨-pedantic.
使用-pedantic意味着gcc应提供标准所需的诊断:
要获得标准所需的所有诊断,您还应指定-pedantic(或-pedantic-errors,如果您希望它们是错误而不是警告)
复合文字不是C99草案标准部分6.6常量表达式所涵盖的常量表达式,我们从章节中看到6.7.8初始化看到:
具有静态存储持续时间的对象的初始化程序中的所有表达式应为常量表达式或字符串文字.
允许gcc接受其他形式的常量表达式作为扩展,来自以下部分6.6:
实现可以接受其他形式的常量表达式.
有趣的是,clang并没有抱怨这个使用 -pedantic
C 语言依赖于什么是常量表达式的确切定义。仅仅因为某些东西看起来“在编译时已知”并不意味着它满足常量表达式的正式定义。
C 语言没有定义非标量类型的常量表达式。它允许实现引入自己的常量表达式类型,但标准定义的常量表达式仅限于标量类型。
换句话说,C 语言没有 为您的类型定义常量表达式的概念struct Test。的任何值struct Test都不是常数。您的复合文字(struct Test) {1}不是常量(也不是字符串文字),因此,它不能用作具有静态存储持续时间的对象的初始值设定项。添加一个const限定词,因为它使用C不会改变任何东西const预选赛没有关系任何以概念常量表达式。在这种情况下,它永远不会有任何区别。
请注意,您的第一个变体根本不涉及复合文字。它使用{ ... }带有常量表达式的原始初始化语法。这对于具有静态存储持续时间的对象是明确允许的。
因此,在最严格的意义上,使用复合字面量的初始化是非法的,而使用普通{ ... }初始化器的初始化是可以的。一些编译器可能接受复合文字初始化作为扩展。(通过扩展常量表达式的概念或采用其他一些扩展路径。请查阅编译器文档以了解其编译的原因。)