我认为C11标准涵盖了这种行为,并表示结果未指定,而且我认为C18在此方面没有进行任何相关更改。
标准语言不容易解析。该标准的相关部分为
§6.7.9初始化。语法记录为:
initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }
initializer-list:
designation
opt
initializer
initializer-list , designation
opt
initializer
designation:
designator-list =
designator-list:
designator
designator-list designator
designator:
[ constant-expression ]
. identifier
请注意,术语之一是Assignment-expression,并且由于a[2] = 1
它无疑是一个赋值表达式,因此对于具有非静态持续时间的数组,它可以在初始化器中使用:
§4对于具有静态或线程存储持续时间的对象,初始化器中的所有表达式都应为常量表达式或字符串文字。
关键段落之一是:
§19初始化应按初始化器列表顺序进行,为特定子对象提供的每个初始化器都将覆盖先前为该子对象列出的所有初始化器;151)
所有未明确初始化的子对象应与具有静态存储持续时间的对象隐式初始化。
151)被覆盖的子对象的任何初始化程序,因此不用于初始化该子对象的初始化程序可能根本不会被评估。
另一个关键段落是:
§23初始化列表表达式的求值相对于彼此是不确定的,因此未指定发生任何副作用的顺序。152)
152)特别地,评估顺序不必与子对象初始化的顺序相同。
我很确定第23段指出了问题中的符号:
int a[5] = { a[2] = 1 };
导致未指明的行为。对的赋值a[2]
是一种副作用,并且表达式的求值顺序不确定地相对于彼此排序。因此,我认为没有一种方法可以诉诸该标准,并声称某个特定的编译器正在正确或不正确地处理此问题。
a[2]=1
计算结果为1
。