指定的初始化器可以合法地引用它在 C99 中初始化的变量吗?

2023-12-12

GCC 和 Clang 都允许指定的初始化器引用正在初始化的结构或数组的成员,但这是合法且定义明确的行为吗?

以下代码示例针对 GCC 和 Clang 进行编译和运行并输出{ .a = 3, .b = 6, }在这两种情况下:

#include <stdio.h>

typedef struct
{
    int a;
    int b;
} foo;

int main()
{
    foo bar = {
        .a = 3,
        .b = bar.a + 3,
    };
    printf("{ .a = %d, .b = %d, }\n", bar.a, bar.b);

    return 0;
}

GCC 生成以下输出(编译器资源管理器链接)对于指定的初始化,这表明该操作对于本示例来说是安全的:

mov     dword ptr [rbp - 4], 0
mov     dword ptr [rbp - 16], 3
mov     eax, dword ptr [rbp - 16]
add     eax, 3
mov     dword ptr [rbp - 12], eax

第 6.7.8 条C99 规范草案讨论了这一点,但我不明白它如何以某种方式定义这种行为。

特别是,第 19 点表明初始化按指定的顺序发生,但第 23 点提到了具有未指定顺序的副作用。我不确定写入结构的数据是否被视为副作用。

  1. 初始化应按初始值设定项列表顺序进行,为特定子对象提供的每个初始值设定项将覆盖同一子对象的任何先前列出的初始值设定项;所有未显式初始化的子对象应与具有静态存储持续时间的对象一样隐式初始化。
  1. 初始化列表表达式中任何副作用发生的顺序未指定

您引用的是旧版本的 C 标准。目前的草案(自 C11 起)对于第 23 点有:

初始化列表表达式的计算相对于彼此是不确定地排序的,因此任何副作用发生的顺序是未指定的。

我认为这意味着编译器可以选择在使用特定初始化表达式之前的任何时间评估该表达式,这意味着它可能发生在它引用的元素初始化之前或之后。

在这种情况下,在初始化表达式中使用同一聚合对象的(可能)未初始化的元素必定会导致不确定的值。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

指定的初始化器可以合法地引用它在 C99 中初始化的变量吗? 的相关文章

随机推荐