【问题标题】:Conditional expression in ternary operator in CC中三元运算符中的条件表达式
【发布时间】:2020-03-30 23:46:18
【问题描述】:

代码

#include <stdio.h>

int main() {
  int i;
  for (i=1; i<=10; i++) {
        (i % 2) ? printf("%d is odd\n", i) : printf("%d is even\n", i);
  }
}

结果

1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
10 is even

在上面的C程序中,为什么即使条件表达式只声明i%2而不是i%2!=0,它仍然可以正常工作?

【问题讨论】:

  • i%2 是一个标量值表达式。在像您这样的表达式上下文中,对于真(非零)或假(零)来说,它隐含地相当大。
  • printf ("%d is %s\n", i, i % 2 ? "odd" : "even") 也可以:)
  • 或者,static const char *msg[] = {"even","odd"}; 在您的循环中,您可以执行类似 printf("%d is %s\n", i, msg[i%2]); 的操作,但现在我们已经超出了您的问题的范围。

标签: c if-statement conditional-statements conditional-operator


【解决方案1】:

在 C 语言中,整数可以在布尔上下文中使用,零表示假,非零表示真。

这就是您的代码有效的原因。对于偶数,表达式num % 2 将为 0(单个假值),而对于奇数,表达式为 1(许多可能的真值之一)。

以下表达式都适用于检测奇数:

num % 2
(num % 2) != 0
((num % 2) != 0) != 0
... and so on, ad untilyougetboredum (like 'ad infinitum' but with limits).

话虽如此,我真的不认为这样做是一个好idea,代码应该尽可能地表达intent,并且这里的意图应该是基于比较来选择执行路径。这意味着,如果您要查找奇数,则应使用 (num % 2) == 1 之类的名称。

您也不需要在这些代码路径的每个中单独调用printf

printf("%d is %s\n", num, ((num % 2) == 1) ? "odd" : "even");

您会注意到我还使用了num 而不是i。这只是我的一个风格问题,与上述意图有关。如果该变量仅用作索引,我很乐意使用 i-type variables(a) 但是,第二个它获得了语义属性(例如检查奇数的数字),我倾向于使用更具描述性的名称。

我对使用简单变量名的人没有问题,我只是更喜欢在我自己的代码中使用更具描述性的名称。


(a) 实际上,在这种情况下,我可能会使用idx,但这也是 CDO(b),甚至对我来说:-)


(b) 强迫症,但顺序正确 :-)

【讨论】:

    【解决方案2】:

    C 没有专用的 boolean 类型。它使用 int 值作为布尔值。也就是说,0 被视为false,任何非零值都被视为true。 尝试打印一些条件

    printf("%d",5==5);
    printf("%d",1>3);
    

    这将输出 1 和 0。

    C 总是使用 1 来表示 true。但是在条件下使用时,任何其他非零值也可以正常工作。

    if(6+1)
        printf("TRUE");
    

    将打印 TRUE。

    这也是我们可以使用这种形式的while循环的原因:

    int i= 10;
    while(i--){
        printf("%d",i);
    }
    

    将打印9876543210。请注意,当 i 变为 0(即false)时它会停止。

    现在回到问题,i%2 总是会导致 0 或 1。如果为 1(真),则运行第一个语句,而如果为 0(假),则运行第二个语句。

    【讨论】:

    • 它确实有一个专用的布尔类型,_Bool
    • 是的。但它仍然解析为整数(0 或 1)。它没有像 Java 等其他语言那样与单纯的 int 不同的专用布尔类型。
    • 不,它确实像其他语言一样具有专用的布尔类型
    猜你喜欢
    • 2019-02-10
    • 2014-09-15
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-03
    • 2012-09-02
    • 1970-01-01
    相关资源
    最近更新 更多