47

我正在编写一个控制台应用程序,它会尝试通过反复试验来“猜测”一个数字,它工作得很好,但它让我想知道我心不在焉地写的某个部分,

代码是:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int x,i,a,cc;
    for(;;){
    scanf("%d",&x);
    a=50;
    i=100/a;
for(cc=0;;cc++)
{
    if(x<a)
    {
        printf("%d was too big\n",a);
        a=a-((100/(i<<=1))?:1);

    }
    else if (x>a)
    {
        printf("%d was too small\n",a);
        a=a+((100/(i<<=1))?:1);

    }
    else
    {
        printf("%d was the right number\n-----------------%d---------------------\n",a,cc);
        break;
    }
}
}
return 0;
}

更具体地说,让我感到困惑的部分是

a=a+((100/(i<<=1))?:1); 
//Code, code
a=a-((100/(i<<=1))?:1);

我曾经((100/(i<<=1))?:1)确保如果100/(i<<=1)返回 0 (或 false),整个表达式将评估为 1 ((100/(i<<=1))?:***1***),并且我将条件的一部分留给如果它为 true 将起作用 empty ((100/(i<<=1))? _this space_ :1),它似乎可以正常工作,但是离开有任何风险那部分条件为空?

4

2 回答 2

70

这是一个 GNU C 扩展(参见?: wikipedia entry),因此为了可移植性,您应该明确说明第二个操作数。

在“真”的情况下,它返回条件的结果。

以下语句几乎是等价的:

a = x ?: y;
a = x ? x : y;

唯一的区别是在第一个语句中,x总是评估一次,而在第二个语句中,x如果它是真的,将被评估两次。所以唯一的区别是评估x有副作用。

无论哪种方式,我都认为这是对语法的一种微妙使用......如果您对维护代码的人有任何同情,您应该明确说明操作数。:)

另一方面,对于一个常见的用例来说,这是一个不错的小技巧。

于 2010-07-23T14:33:54.807 回答
24

这是对 C 语言的GCC 扩展。当 之间没有出现任何内容时?:,则在真实情况下使用比较的值。

条件表达式中的中间操作数可以省略。那么如果第一个操作数非零,它的值就是条件表达式的值。

因此,表达式

    x ? : y

如果 x 不为零,则具有 x 的值;否则,y 的值。

这个例子完全等同于

    x ? x : y

在这种简单的情况下,省略中间操作数的能力并不是特别有用。当它变得有用时,第一个操作数确实或可能(如果它是宏参数)包含副作用。然后在中间重复操作数将执行两次副作用。省略中间操作数会使用已经计算的值,而不会产生重新计算的不良影响。

于 2010-07-23T14:32:45.437 回答