c-faq和我的编译器之间的矛盾

时间:2010-09-22 20:50:02

标签: c operator-precedence

C-faq表示代码:

int i = 7;
printf("%d\n", i++ * i++);

打印49.无论评价顺序如何,都不应该打印56? 当我在Turbo C 3.0编译器上运行此代码时,它给出了56的输出。为什么会出现矛盾?

4 个答案:

答案 0 :(得分:10)

没有矛盾。从用户的角度来看,问题是措辞,如果你仔细阅读答案,你会发现这句话

  

包含的代码的行为   多重,模棱两可的副作用   总是未定义。

因此它可能会打印49或56.毕竟,未定义的行为是未定义的。这就是没有真正矛盾的原因。您可能想要了解所谓的序列点。

答案 1 :(得分:4)

因为未定义的行为。编译器可以做任何想做的事情:它可以使代码打印56,49或“你的妈妈”,编译器仍然符合标准。

您不能在两个序列点之间多次修改相同的值。

答案 2 :(得分:3)

表达式i++ * i++调用未定义的行为,因此任何结果都是可能的。

为什么不定义?因为语言标准如此:

6.5 Expressions
...
2  Between the previous and next sequence point an object shall have its 
   stored value modified at most once by the evaluation of an expression.72) 
   Furthermore, the prior value shall be read only to determine the value 
   to be stored.73)
...
73) This paragraph renders undefined statement expressions such as

    i = ++i + 1;
    a[i++] = i;

while allowing

    i = i + 1;
    a[i] = i;

其中“未定义的行为”表示

3.4.3
1 undefined behavior
  behavior, upon use of a nonportable or erroneous program construct or of 
  erroneous data, for which this International Standard imposes no requirements

2 NOTE Possible undefined behavior ranges from ignoring the situation 
  completely with unpredictable results, to behaving during translation 
  or program execution in a documented manner characteristic of the environment 
  (with or without the issuance of a diagnostic message), to terminating a 
  translation or execution  (with the issuance of a diagnostic message).

3 EXAMPLE An example of undefined behavior is the behavior on integer overflow.

强调我的。

答案 3 :(得分:2)

C-faq真的这么说吗?您正在使用插入序列点修改变量(i)两次,这只是给出了未定义的行为,无论是更多还是更少。它可以打印49或56,或73295,或者根本不打印,或者“格式化硬盘驱动器......”(然后继续这样做)。

编辑:关于可能发生什么,它归结为:通过后增量,增量部分可以在您检索值和下一个序列点之间的任何地方发生。生成的代码很容易就像这样:

int temp = i;
++i;
int temp2 = i;
++i;

printf("%d\n", temp * temp2);

另一方面,它也可以这样:

int temp = i;
int temp2 = i;
++i;
++i;
printf("%d\n", temp * temp2);

虽然这两个中的一个很可能,但该标准并未强制要求任何一个。正如我上面所说,它是未定义的行为,这意味着C标准不会对代码可以做的任何任何限制。