Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c99中的静态结构初始化_C_Gcc_Struct_Compound Literals - Fatal编程技术网

c99中的静态结构初始化

c99中的静态结构初始化,c,gcc,struct,compound-literals,C,Gcc,Struct,Compound Literals,在c99/gnu99模式下,在GCC中使用复合文本进行静态结构初始化时,我遇到了一个奇怪的行为 显然这很好: struct测试 { INTA; }; 静态结构测试tt={1};/*1 */ 然而,这不是: 静态结构测试tt=(结构测试){1};/*2 */ 这会触发以下错误: 初始值设定项元素不是常量 此外,这也无助于: static struct Test tt=(const struct Test){1};/*3 */ 我知道静态结构的初始值应该是编译时常量。但我不明白为什么这个最简单

c99/gnu99
模式下,在
GCC
中使用复合文本进行静态结构初始化时,我遇到了一个奇怪的行为

显然这很好:

struct测试
{
INTA;
};
静态结构测试tt={1};/*1 */
然而,这不是:

静态结构测试tt=(结构测试){1};/*2 */
这会触发以下错误:

初始值设定项元素不是常量

此外,这也无助于:

static struct Test tt=(const struct Test){1};/*3 */
我知道静态结构的初始值应该是编译时常量。但我不明白为什么这个最简单的初始化表达式不再被认为是常量?这是否由标准定义

我问这个问题的原因是,我遇到了一些在gnu90模式下用GCC编写的遗留代码,这些代码使用这种复合文本构造进行静态结构初始化(2)。显然,这是当时的GNU扩展,后来被C99采用

现在它导致用
GNU90
成功编译的代码既不能用
C99
编译,也不能用
GNU99
编译

他们为什么要这样对我?

这个(HT对cremno),bug报告说:

我认为我们应该只允许使用静态 即使在gnu99/gnu11中,复合文字的存储持续时间也是如此。[...] (但要用-pedantic警告。)

从中我们可以看出,静态存储持续时间对象的初始化应该作为扩展来支持:

作为GNU扩展,GCC允许使用静态 按复合文字表示的存储持续时间(在ISO中不可能 C99,因为初始值设定项不是常量)

这在《通用条款》第5.2条中已得到修正。因此,在
gcc 5.2
中,只有在使用
-pedantic
标志时,您才会收到此警告,如果没有
-pedantic
,该标志不会出现问题

使用
-pedantic
意味着按照标准要求提供诊断:

要获得标准要求的所有诊断,您应该 如果需要,还可以指定-pedantic(或-pedantic)错误 错误(而不是警告)

复合文字不是C99标准草案第6.6节“常量表达式”所涵盖的常量表达式,我们从第6.7.8节“初始化”中看到:

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

gcc可以接受其他形式的常量表达式作为扩展,参见第6.6节:

实现可以接受其他形式的常量表达式


有趣的是,clang并没有抱怨使用
-pedantic
引用
C11
标准,第§6.5.2.5章,复合文字,第3段,(强调我的意思)

由括号中的类型名和括号中的初始值设定项列表组成的后缀表达式是复合文字它提供一个未命名的对象,其值由初始值设定项列表给出。

因此,复合文字被视为未命名对象,而不被视为编译时常量

正如不能使用另一个变量初始化静态变量(从C99开始),也不能再使用此复合文字来初始化静态变量。

ISO C99是否支持复合文字()。但是,当前<>强>只有< /强> GNU扩展提供了对复合对象的强存储>静态存储时间> /St>的初始化,而仅针对C90和C++。p> 复合文字看起来像包含初始值设定项的强制转换。它的值是强制转换中指定类型的对象,包含初始值设定项中指定的元素;这是一个左值。作为一种扩展,GCC支持C90模式和C++中的复合文本,尽管C++中的语义有所不同。 通常,指定的类型是结构。假设
struct foo
和structure的声明如下所示:

下面是一个使用复合文字构建
struct foo
的示例:

 structure = ((struct foo) {x + y, 'a', 0});
这相当于编写以下内容:

 {
   struct foo temp = {x + y, 'a', 0};
   structure = temp;
 }
GCC扩展
作为GNU扩展,GCC允许通过复合文本初始化具有静态存储持续时间的对象(这在ISO C99中是不可能的,因为初始值设定项不是常量)。如果复合文字和对象的类型匹配,则它的处理方式就好像只使用括号中的列表初始化对象一样。复合文字的初始值设定项列表必须是常量。如果要初始化的对象具有未知大小的数组类型,则大小由复合文字大小确定

注意:
帖子上的编译器标签只包括GCC;但是,您可以将其与C99(以及多个GCC版本)进行比较。需要注意的是,GCC向其编译器添加扩展功能的速度比大型C标准组更快。这有时会导致错误行为和版本之间的不一致。同样重要的是要注意,对一个众所周知的和流行的编译器的扩展,但不符合公认的C标准,会导致潜在的不可移植代码。在决定使用大型C工作组/标准组织尚未接受的扩展时,始终值得考虑目标客户。(见和。)


有几个例子表明,规模较小、更灵活的开源C工作组或委员会通过添加扩展来响应用户群的兴趣。例如,.

有趣的是,
clang
并没有抱怨这个代码,即使是
 {
   struct foo temp = {x + y, 'a', 0};
   structure = temp;
 }
 static struct foo x = (struct foo) {1, 'a', 'b'};
 static int y[] = (int []) {1, 2, 3};
 static int z[] = (int [3]) {1};
#include <stdio.h>

struct Test
{
    int a;
};

static struct Test *tt = &((struct Test) {1}); /* 2 */

int main(void)
{
    printf("%d\n", tt->a);

    return 0;
}