多变量比较内联未定义行为?

时间:2013-01-30 20:31:11

标签: c++ c undefined-behavior

我告诉我的一位朋友(正在学习C)他不能同时做多个变量比较:

int main(){
    int a[4];

    scanf("%d %d %d %d", &a[0], &a[1], &a[2], &a[3]);

    if(a[0] < a[1] < a[2] < a[3]){
        printf("OK!\n");

    }

    else{
        printf("I've told ya\n");

    }

}

所以,为了证明我是对的,我已经编写了上面的程序,然后我用1 2 3 4执行了它。令人惊讶的是,它打印了OK!。所以我不知道该告诉他什么,因为我确信这不对。

最后,它是否是未定义的行为?

7 个答案:

答案 0 :(得分:12)

不,它定义明确。它只是与你期望的语义有不同的语义。

表达式评估如下:

if (((a[0] < a[1]) < a[2]) < a[3]) {

每次比较都会产生布尔(01)结果。

a[0] < a[1]的(布尔)结果与a[2]进行比较,并将该比较的(布尔)结果与a[3]进行比较。

我确信有一些合法的用例,但它们充其量是罕见的。

表达您想要表达的内容的正确方法是

if (a[0] < a[1] && a[1] < a[2] && a[2] < a[3]) {

答案 1 :(得分:4)

这不是未定义的行为,它只是不按照您的想法行事。它相当于

(((a[0] < a[1]) < a[2]) < a[3])

1表示true,0表示false。因此,如果[0]小于[1],那么它将[2]与1进行比较,否则为零。等等。

答案 2 :(得分:4)

这不是未定义的行为,它是意外的行为

在C和C ++中,你不能像那样进行类似数学的比较。您可以一次比较两件事。所以,如果你想要a < b < c < d,你必须写:

if (a < b && b < c && c < d)
    ...

答案 3 :(得分:3)

由于你将C ++融入其中,你可以非常简单地进行

if ( std::is_sorted(a, a+4) )
    puts("OK!");

答案 4 :(得分:2)

这是定义的行为,但没有达到预期的效果,所以不要这样做。

你的表达成为:

((a[0] < a[1]) < a[2]) < a[3]

其中每个x&lt; y被转换为1或0 - 这意味着如果[3]大于1,它总是为真,如果[3]大于0,则可能为真。

答案 5 :(得分:2)

这不是未定义的行为,但它没有做他认为的行为。 &LT;是从左到右的关联,因此首先评估a[0] < a[1],结果为true。然后评估true < a[2](相当于1 < a[2]),得到true。等等。你巧合只得到了正确的结果。例如,“2 1 0 1”也将产生真实。使用

a[0] < a[1] && a[1] < a[2] && a[2] < a[3]

或更一般地说,如果您的数组很长:

for(i=1,ok=1;i<n&&ok;i++)ok &= a[i-1] < a[i];

答案 6 :(得分:1)

&lt;的评估顺序。运算符,当这样出现时,是明确定义的。您编写的代码等同于:

bool x;

x = a[0] < a[1];

if(x == true)
{
  x = true < a[2]; 
}
else
{
  x = false < a[2]; 
}

if(x == true)
{
  x = true < a[3]; 
}
else
{
  x = false < a[3]; 
}

if(x == true)
{
  printf("OK!\n");
}
else
{
  printf("I've told ya\n");
}

true始终求值为整数1,false为0.正如您所知,此代码完全没有意义。