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

发布于 2024-09-24 16:59:57 字数 252 浏览 0 评论 0原文

C-faq 说代码:

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

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

The C-faq says that the code:

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

prints 49. Regardless of the order of evaluation, shouldn't it print 56?
When I ran this code on my Turbo C 3.0 compiler it gave me the output of 56. Why is there a contradiction?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

比忠 2024-10-01 16:59:57

这并不矛盾。这个问题是从用户角度出发的,如果你仔细阅读答案,你会发现这样的评论

代码的行为包含
多种模糊的副作用
始终未定义。

所以它可能会打印 49 或 56。毕竟,未定义的行为是未定义的。这就是为什么不存在真正的矛盾。您可能想加深对所谓序列点的理解。

There is no contradiction. The question was worded from a user perspective, and if you carefully read the answer, you will find the remark

The behavior of code which contains
multiple, ambiguous side effects has
always been undefined.

So it might print 49, or 56. Undefined behavior is, after all, undefined. This is why there is no real contradiction. You might want to brush up your understanding of what are called sequence points.

白色秋天 2024-10-01 16:59:57

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

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

Because it's undefined behavior. The compiler can do whatever it wants: it can make the code print 56, 49, or "your mom", and the compiler would still be standards-conforming.

You can't modify the same value more than once between two sequence points.

电影里的梦 2024-10-01 16:59:57

表达式 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.

强调我的。

The expression i++ * i++ invokes undefined behavior, so any result is possible.

Why is it undefined? Because the language standard says so:

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;

where "undefined behavior" means

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.

Emphasis mine.

假扮的天使 2024-10-01 16:59:57

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 标准不会对代码的功能施加任何限制。

Does the C-faq really say that? You're modifying a variable (i) twice with an intervening sequence point, which simply gives undefined behavior, nothing more or less. It could print 49 or 56, or 73295, or nothing at all, or "Formatting hard drive..." (and proceed to do exactly that).

Edit: As to what's likely to happen, it comes down to this: with a post-increment, the increment part can happen anywhere between the time you retrieve the value, and the next sequence point. The generated code could easily act like this:

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

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

On the other hand, it could also act like this:

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

While one of these two is likely, the standard doesn't mandate either one. As I said above, it's undefined behavior, which means the C standard doesn't place any limitation on what the code could do.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文