有副作用的初始化器

4

C18标准在6.7.9/2处指出:

初始化程序不能为未包含在正在初始化的实体中的对象提供值。

这个意思并不是很清楚。这里有一个相关的话题:字符串初始化的不一致gcc诊断。我引用的条款被用来解释以下初始化产生的错误:

//error: excess elements in array initializer char a[5]
char a[5] = {'h','e','l','l','o','\0'}; 

当初始化列表的长度超过正在初始化的数组的大小时。

但是请考虑一个更简单的例子

int main(void){
    int a;
    int b = (a = 3);
}

这里的初始化程序是 (a = 3),它是一个赋值表达式。该初始化程序将一个值分配给另一个对象,这应该会引起约束违规。
为什么没有打印任何诊断信息呢?
1个回答

5

这并不是“为a提供一个值”的意思,它只是一个具有将值存储在a中的副作用的表达式。 “提供值”应该在初始化的上下文中理解; 它不是分配时使用的措辞。

标准中所述语言试图传达的一个不那么琐碎的例子可能是:

struct {
    char a[4];
    char b[4];
} foo = { { 'h', 'e', 'l', 'l', 'o' } };

我认为(如有错误请指出),以下内容是有效的C代码,尽管有点令人困惑:

struct {
    char a[4];
    char b[4];
} foo = { 'h', 'e', 'l', 'l', 'o' };

3
是的,后一种方法也是有效的。像 { { 'h', 'e', 'l', 'l' }, 'o' } 这样的丑陋写法也是可以的。 - Antti Haapala -- Слава Україні
@AnttiHaapala,您的示例利用了省略{}的能力,如果initializer-list只包含一个元素,是吗? - St.Antario
@AnttiHaapala 6.7.9/20: 仅使用列表中足够的初始化器来对子聚合或包含联合体的第一个成员进行初始化;任何剩余的初始化器则留给初始化当前子聚合或包含联合体所属的聚合的下一个元素或成员。这是你使用的吗? - St.Antario
@AnttiHaapala 有点扩展你的例子,我尝试了以下代码:struct str{ char a[4]; char b[4]; char c[4]; char d[4]};。应用6.7.9/20,我期望以下代码可以正常工作:struct str foo = { {'h', 'e'}, 'l', 'l', 'o', 'w', 'o', 'r', {'l', 'd'} };,并且foo.c将被初始化为(or\0\0),但是却打印出了warning: braces around scalar initializer警告信息。演示 - St.Antario
还有 int a[4] = { [5] = 3 }; - Eric Postpischil
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接