C89标准中带初始化器的逗号分隔声明符序列的表达式求值顺序
C89标准中带初始化器的逗号分隔声明符序列的求值顺序规定
核心规定与示例分析
在C89(ANSI C X3.159-1989)标准中,声明语句里用于分隔多个声明符的逗号并非逗号运算符,仅作为声明符的分隔标点。虽然《声明》《初始化》《程序执行》等正文章节未直接明确这类场景下的求值顺序,但结合附录C的序列点规定可明确推导:
附录C明确指出,初始化器列表中的逗号(包括声明中分隔不同初始化器的逗号)末尾存在序列点。序列点的核心作用是:序列点之后的代码执行前,序列点之前所有表达式的求值运算与副作用必须完全完成。
针对你给出的示例代码:
int t = 1; void block (void) { int a = (t *= 2), b = (t *= 3); /* Is it guaranteed that a==2 and b==6 ? */ }
分隔a与b的逗号末尾是序列点,这意味着a的初始化表达式(t *= 2)的求值(计算出2)与副作用(将t修改为2)必须在b的初始化表达式(t *= 3)执行前全部完成。因此可以完全保证a的值为2,b的值为6,代码行为是完全定义的。
类似问题的分析
对于类似int a=0, b=a++, c=a++;的声明语句,C89标准下的行为同样是确定的:
- 首先完成
a的初始化(赋值为0),到达第一个序列点; - 接着执行
b=a++:此时a的值为0,b被赋值为0,随后a自增为1,完成后到达下一个序列点; - 最后执行
c=a++:此时a的值为1,c被赋值为1,随后a自增为2。
整个过程中每个初始化步骤都被序列点分隔,前一步的所有副作用都会在下一步开始前完成,不存在未定义行为。
内容的提问来源于stack exchange,提问作者green red
相关产品推荐
相关产品推荐

