【问题标题】:Is it a comma operator in declaration and initialization statement for C?它是 C 的声明和初始化语句中的逗号运算符吗?
【发布时间】:2017-01-18 18:36:49
【问题描述】:

我在看C Programming Language,发现这句话:

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

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

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

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

【问题讨论】:

  • 声明也按顺序工作。更有趣的情况是f(a += b, a)。
  • 这行得通。但是,从风格上讲,我不喜欢使用逗号声明,而是喜欢这样做:int a = 1;int b = a + 1;int c = b + a + 1;int d = c + b + a + 1;[在单独的行]。我读过的大多数风格指南也更喜欢分割线方法。 IMO,在查看大量代码时,使用逗号更难阅读/理解[快速]。对我来说,sequential 的意图更加清晰。其他人,看到逗号可能不得不研究这个,就像你的问题一样。另请注意,我还添加了一些空白作为视觉辅助。
  • 我认为f(a += b, a) 是一种糟糕的编码风格,因为它已经被大量讨论过不要像printf("%d, %d\n", a++, a++); 那样使用,而且C 标准也不能保证结果。但是我没有看到关于int a = 1, b = a + 1 ... 的相同讨论,这就是我问这个问题的原因。
  • 同意这不是好的编码风格。但仍然想弄清楚它是否总是有效。 :-)
  • @KerrekSB 函数调用中的逗号不是“逗号运算符”,并且不能保证顺序(事实上,在 80 年代使用蒸汽驱动的 C 编译器时,它很可能是相反的顺序,因为参数是从右向左推送的——但从来没有任何保证)。

标签: c comma-operator


【解决方案1】:

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

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

在标准中找到正确的措辞来证明这种说法比我预期的要难。它实际上在声明符部分。

§6.7 声明

语法

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

…

init-declarator-list:
初始化声明器
init-declarator-list , init-declarator

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

¶6 声明说明符由一系列说明符组成,这些说明符指示链接、存储持续时间和声明符表示的实体的部分类型。 init-declarator-list 是一个逗号分隔的声明符序列,每个声明符可能有额外的类型信息,或初始化器,或两者兼有。声明符包含被声明的标识符(如果有的话)。

¶7 如果对象的标识符被声明为没有链接,则对象的类型应在其声明符的末尾完成,或者在其初始化声明符的末尾(如果它具有初始化程序);在函数参数的情况下(包括在原型中),它是调整后的 需要完整的类型(参见 6.7.6.3)。

§6.7.6 声明符

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

AFAICS, §6.7.9 Initializers 不添加任何相关内容。

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

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

【讨论】:

  • 完全解释了这一点。谢谢并标记为答案。
【解决方案2】:

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

【讨论】:

  • 请参考您的断言,最好来自标准。
  • 维基百科文章确实指出 init-declarators 之间的逗号处有序列点,但逗号不是逗号运算符。
  • 发现它确实很好地解释了这个问题。但是,随着其他答案的解释更多,我认为将其标记为答案可能对其他人有更多帮助。谢谢!
猜你喜欢
  • 2020-12-29
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 2011-06-26
  • 1970-01-01
  • 1970-01-01
  • 2019-08-11
相关资源
最近更新 更多