多个对象声明中的逗号是否会像逗号运算符一样引入序列点?

问题描述 投票:0回答:2

我在看《C 编程语言》,发现这样一句话:

在声明中分隔...变量的逗号...不是逗号运算符,并且不保证从左到右计算。

如果是,这段代码中是否有逗号运算符?

int a=1, b=a+1, c=b+a+1, d=c+b+a+1;

我非常确定它会起作用。但如果它们不是逗号运算符并且不能保证从左到右的顺序,那么上面的语句可能会失败,对吗?

c language-lawyer definition comma-operator sequence-points
2个回答
13
投票

声明中的逗号不是表达式中的逗号运算符(声明不是表达式,尽管声明中的初始化是表达式)。问题中的引用是准确的,它表示单独的声明不是逗号运算符。

但是,每个声明符在其后面的逗号或分号处都是完整的,因此问题中的变量定义是完全定义的行为。当这句话暗示不能保证从左到右的评估时,这句话是不正确的——尽管这是一个微妙的语言剖析。如果逗号是逗号运算符,那么这一事实将保证从左到右的评估;由于它们不是逗号运算符,因此从左到右的保证不会由逗号运算符的定义产生。但是,因为每个声明符后面都有序列点,所以从左到右的估值是单独保证的。

在标准中找到正确的措辞来证明这一主张比我预想的要困难。它实际上在声明符部分。

§6.7 声明

语法

声明:
声明说明符 init-declarator-listopt ;

初始化声明符列表:
init 声明符
初始化声明器列表,初始化声明器

初始化声明符:
声明者
声明符=初始化器

¶6 声明说明符由一系列说明符组成,这些说明符指示声明符所表示的实体的链接、存储持续时间和部分类型。 init-declarator-list 是一个以逗号分隔的声明符序列,每个声明符都可能具有附加类型信息或初始值设定项,或两者兼而有之。声明符包含正在声明的标识符(如果有)。

¶7 如果对象的标识符是在没有链接的情况下声明的,则该对象的类型应在其声明符末尾处完成,或者在其初始化声明符末尾处(如果它具有初始值设定项);对于函数参数(包括原型),它是调整后的 需要填写的类型(参见 6.7.6.3)。

§6.7.6 声明符

¶3 完整声明符 是不属于另一个声明符的声明符。完整声明符的末尾是一个序列点。

AFAICS,§6.7.9 初始化器 未添加任何相关内容。

顺序点至关重要;这意味着在继续之前,左边的所有内容都已完全评估并且副作用已完成;它意味着从左到右的排序,因此问题中的初始化已完全定义。

有点奇怪的是,序列点位于完整的声明符之后,而不是初始化器之后;不过我认为这并不重要。


0
投票

不,可能不会,因为在声明中逗号充当序列点,保证评估将按提到的顺序执行。 您可以在这里找到更多信息:序列点

© www.soinside.com 2019 - 2024. All rights reserved.