首页 > 解决方案 > 这是未定义的行为吗

问题描述

据我了解,这个程序应该有未定义的行为。

#include <stdio.h>

int main()
{
   int a = 3, b = 3, c = 10, d = 20;
   int e = (a++ * ++b)-((c / b) * a) + d;
   printf("%d", e)  ;

   return 0;
}

C99 标准 §6.5 ¶2 说

在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的评估修改一次。此外,应仅读取先验值以确定要存储的值。

因此,在定义'e',ab被读取的行中,不仅是为了确定要在aand中存储什么b,而且是为了计算表达式((c / b) * a)

但是,即使使用 .gcc 也不会发出警告-Wsequence-point warning

我在这里想念什么?

标签: cgcclanguage-lawyer

解决方案


使用 clang 编译器(版本 - clang-1001.0.46.4)编译时,收到以下警告:

   p.c:6:19: warning: unsequenced modification and access to 'b' [-Wunsequenced]
       int e = (a++ * ++b)-((c / b) * a) + d;
                        ^        ~
   p.c:6:14: warning: unsequenced modification and access to 'a' [-Wunsequenced]
       int e = (a++ * ++b)-((c / b) * a) + d;
                ^                     ~

来自 C11 Standards#6.5p2 [强调添加]

2如果标量对象上的副作用相对于同一标量对象上的不同副作用或使用同一标量对象的值的值计算是未排序的,则行为未定义。如果一个表达式的子表达式有多个允许的排序,则如果在任何排序中出现这种未排序的副作用,则行为未定义。84)

该表达式调用未定义的行为。


编辑:

带有 标记的问题gcc,因此为了完整回答,下面是使用gcc带有-Wall选项的编译器编译时的输出:

p.c:6:19: warning: operation on 'b' may be undefined [-Wsequence-point]
    int e = (a++ * ++b)-((c / b) * a) + d;
                   ^
p.c:6:14: warning: operation on 'a' may be undefined [-Wsequence-point]
    int e = (a++ * ++b)-((c / b) * a) + d;
              ^

请注意,如果我们在编译时没有指定任何选项(如-Wallor -Wsequence-pointgcc,则不会对有问题的表达式给出任何警告消息,但clang编译器并非如此。


推荐阅读