我告诉我的一位朋友(正在学习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!
。所以我不知道该告诉他什么,因为我确信这不对。
最后,它是否是未定义的行为?
答案 0 :(得分:12)
不,它定义明确。它只是与你期望的语义有不同的语义。
表达式评估如下:
if (((a[0] < a[1]) < a[2]) < a[3]) {
每次比较都会产生布尔(0
或1
)结果。
将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.正如您所知,此代码完全没有意义。