【问题标题】:Can I use conditions directly to assign a variable in C我可以直接使用条件在C中分配一个变量吗
【发布时间】:2015-11-09 19:09:58
【问题描述】:
bool bVal;
int a = 5;
int b = 2;

bVal = (bool)a>b;

声明bVal =a>b; 是否可接受。当然,这对我来说很好用。

但我看到人们使用这样的东西:

#define CHECK_bIsTrue(value)  ((value) ? TRUE : FALSE)

如果只是布尔值,为什么还要使用三元运算符?

【问题讨论】:

  • bVal = (bool)a>b; 是错误的(在这里会给出错误的结果),但 bVal = a>b; 是正确的。
  • 我认为#define 宏将真实值(任何值!= 0)“标准化”为 TRUE。如果 value 已经是布尔值,这似乎是多余的。
  • @vigneswaran j 有时,表达式必须恰好返回 1 或 0。考虑例如按位与运算符 x & 8。如果确实设置了相应的位,则表达式不会返回 1。
  • 您也可以使用!!(<some expression>)(例如!!(x & 8))将结果折叠为0或1。虽然它有点神秘。
  • bVal = (bool)a>b; 表示bVal = ((bool)a)>b; 所以它不会返回正确的结果。

标签: c conditional-statements ternary-operator


【解决方案1】:

是的,bVal = a>b; 完全正确。

对这种简单的赋值使用三元组是大材小用,使用宏是不合理的。

【讨论】:

    【解决方案2】:

    声明a > b 保证产生非零或零,这对于C 运算符如ifwhile 等来说已经足够了。但有时人们出于某种原因想要肯定得到1(或TRUE) 或 0 (或 FALSE) 这就是他们使用宏的原因。

    【讨论】:

    • 首选来自 stdbool.h 的 truefalse。不要使用TRUEFALSE,这表明你的代码已经过时了 pre-C99 风格。
    【解决方案3】:

    有时你需要恰好 1 或 0 来表示某些表达式。

    考虑一个例子。

    假设您决定编写一些适用于整数数组的通用函数,该函数将根据给定条件进行计数。

    函数可以如下所示

    int count( int a[], size_t n, int predicate( int x ) )
    {
        int cnt = 0;
    
        for ( size_t i = 0; i < n; i++ ) cnt += predicate( a[i] );
    
        return cnt;
    }
    

    如您所见,该函数的实现方式是将谓词的结果添加到变量cnt

    cnt += predicate( a[i] );
    

    不过,谓词不一定要准确返回 1 或 0。

    例如,可以像谓词一样使用的一些标准 C 函数通常返回一些非零值来指定条件为真。比如根据&lt;ctype.h&gt;中对isdigitisalpha等函数的描述,C标准中有写(7.4.1字符分类函数)

    1 如果和 只有当参数 c 的值符合 功能描述。例如让我们假设有

    C 标准中有很多这样的函数(例如,考虑一个函数strcmp)。

    因此返回到函数count的示例,如果它按编写方式使用,则其执行结果可能不正确

    例如,假设已经存在函数,如果设置了数字的第二位,则返回 非零

    int is_2nd_bit_set( int x ) { return x & 2; }
    

    在这种情况下,如果你运行这个程序

    #include <stdio.h>
    
    int count( int a[], size_t n, int predicate( int x ) )
    {
        int cnt = 0;
    
        for ( size_t i = 0; i < n; i++ ) cnt += predicate( a[i] );
    
        return cnt;
    }
    
    int is_2nd_bit_set( int x ) { return x & 2; }
    
    int main( void )
    {
        int a[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10 };
        const size_t N = sizeof( a ) / sizeof( *a );
    
        printf( "there are %d numbers that have 2nd bit set\n", count( a, N, is_2nd_bit_set ) );
    }    
    

    你得到错误的结果

    there are 10 numbers that have 2nd bit set
    

    要得到正确的结果,你必须按照以下方式重写函数中的相应语句

    for ( size_t i = 0; i < n; i++ ) cnt += ( predicate( a[i] ) ? 1 : 0 );
    

    一些程序员使用否定运算符!对一个表达式应用两次,正好得到 1 或 0。例如

    for ( size_t i = 0; i < n; i++ ) cnt += !!predicate( a[i] );
    

    但是这样的代码会让读者感到困惑。

    现在,当 C 标准中引入 _Bool 类型时,语句可以更简单地编写

    for ( size_t i = 0; i < n; i++ ) cnt += ( _Bool )predicate( a[i] );
    

    【讨论】:

      【解决方案4】:

      由于历史原因,所有产生布尔结果的 C 操作数,例如 &gt; 运算符,实际上返回值为 1 或 0 的类型 int。这使得 C 很奇怪,因为即使现在有布尔类型在该语言中,所有逻辑和布尔运算仍然适用于 int 类型。

      (bool)a&gt;b 是错误的,因为它没有意义:它在操作之前将a 操作数转换为bool。但是操作本身将两个操作数提升为int,所以演员唯一能实现的就是(不太可能和不相关的)价值损失。

      如果您对类型正确性过于挑剔,您可以使用bVal = (bool)(a&gt;b); 将结果类型显式转换为bool,这与bVal = a&gt;b; 基本相同。两者都可以。

      您发布的宏不仅毫无意义,而且是不好的做法。不应该尝试用令人讨厌的类似函数的宏来发明 C 语言的个人版本。另外,使用预定义的宏truefalse,而不是非标准的TRUEFALSE

      【讨论】:

        猜你喜欢
        • 2012-02-08
        • 2013-08-16
        • 1970-01-01
        • 2019-08-31
        • 2013-10-13
        • 2023-03-20
        • 1970-01-01
        • 1970-01-01
        • 2011-03-16
        相关资源
        最近更新 更多