代码之家  ›  专栏  ›  技术社区  ›  Joe Schneider

逗号运算符是如何工作的

  •  160
  • Joe Schneider  · 技术社区  · 18 年前

    逗号运算符如何在C++中工作?

    例如,如果我这样做:

    a = b, c;  
    

    A最终等于B还是C?

    (是的,我知道这很容易测试——只需要在这里记录下来,以便有人快速找到答案。)

    更新: 这个问题在使用逗号运算符时暴露了一个细微差别。只需记录:

    a = b, c;    // a is set to the value of b!
    
    a = (b, c);  // a is set to the value of c!
    

    这个问题实际上是由代码中的一个错误引起的。目的是什么

    a = b;
    c = d;
    

    变成

    a = b,    //  <-  Note comma typo!
    c = d;
    
    9 回复  |  直到 8 年前
        1
  •  74
  •   msanford    8 年前

    它等于 b .

    逗号运算符的优先级低于赋值。

        2
  •  122
  •   Konrad Rudolph    14 年前

    注意,逗号运算符可能在C++中被重载。因此,实际行为可能与预期行为非常不同。

    作为一个例子, Boost.Spirit 非常巧妙地使用逗号运算符实现符号表的列表初始值设定项。因此,它使以下语法成为可能和有意义的:

    keywords = "and", "or", "not", "xor";
    

    请注意,由于运算符优先级的原因,代码是(有意!)相同的

    (((keywords = "and"), "or"), "not"), "xor";
    

    也就是说,第一个被调用的运算符是 keywords.operator =("and") 它返回一个代理对象,在该对象上 operator, S被调用:

    keywords.operator =("and").operator ,("or").operator ,("not").operator ,("xor");
    
        3
  •  118
  •   efotinis    17 年前

    逗号运算符具有 最低的 所有C/C++操作符的优先级。因此,它始终是最后一个绑定到表达式的表达式,这意味着:

    a = b, c;
    

    相当于:

    (a = b), c;
    

    另一个有趣的事实是逗号运算符引入了 sequence point . 这意味着表达式:

    a+b, c(), d
    

    保证有三个子表达式( A+B , C() D )按顺序评估。如果它们有副作用,这是很重要的。通常情况下,编译器可以按其认为合适的顺序计算子表达式;例如,在函数调用中:

    someFunc(arg1, arg2, arg3)
    

    参数可以按任意顺序计算。注意,函数调用中的逗号是 运算符;它们是分隔符。

        4
  •  60
  •   CygnusX1 Stack Overflow is garbage    12 年前

    逗号运算符:

    • 具有最低优先级
    • 是左关联的

    逗号运算符的默认版本是为所有类型(内置和自定义)定义的,其工作方式如下-给定 exprA , exprB :

    • exprA 被评估
    • 结果 EXPRA 被忽略
    • exprB 被评估
    • 结果 EXPRB 作为整个表达式的结果返回

    对于大多数运算符,编译器可以选择执行顺序,如果不影响最终结果,甚至需要跳过执行。 false && foo() 将跳过呼叫 foo )但是,逗号运算符并非如此,上述步骤将始终发生。 * .

    实际上,默认的逗号运算符的工作方式几乎与分号相同。不同之处在于,用分号分隔的两个表达式构成两个单独的语句,而逗号分隔则将所有表达式保持为单个表达式。这就是为什么在以下场景中有时使用逗号运算符的原因:

    • C语法需要一个 表达 不是声明。例如在 if( HERE )
    • C语法需要一个语句,而不是更多语句,例如在初始化 for for ( HERE ; ; )
    • 如果要跳过大括号并保留单个语句: if (foo) HERE ; (请不要这样做,真的很难看!)

    当语句不是表达式时,分号不能替换为逗号。例如,这些是不允许的:

    • (foo, if (foo) bar) ( if 不是表达式)
    • int x,int y(变量声明不是表达式)

    在您的案例中,我们有:

    • a=b, c; 相当于 a=b; c; 假设 a 是不重载逗号运算符的类型。
    • a = b, c = d; 相当于 a=b; c=d; 假设 是不重载逗号运算符的类型。

    请注意,并非每个逗号实际上都是逗号运算符。一些逗号的含义完全不同:

    • int a, b; ---变量声明列表是逗号分隔的,但这些不是逗号运算符
    • int a=5, b=3; ---这也是一个逗号分隔的变量声明列表。
    • foo(x,y) ---逗号分隔的参数列表。事实上, x y 可在中评估 任何 秩序!
    • FOO(x,y) ---逗号分隔的宏参数列表
    • foo<a,b> ---逗号分隔的模板参数列表
    • int foo(int a, int b) ---逗号分隔参数列表
    • Foo::Foo() : a(5), b(3) {} ---类构造函数中逗号分隔的初始值设定项列表

    * 如果应用优化,这并不完全正确。如果编译器认识到某段代码对其余部分绝对没有影响,它将删除不必要的语句。

    进一步阅读: http://en.wikipedia.org/wiki/Comma_operator

        5
  •  37
  •   jww avp    11 年前

    价值 a b 但价值 表达式 c . 也就是说,在

    d = (a = b, c);
    

    A等于 d 等于 C .

        6
  •  8
  •   prakash    18 年前

    B的值将分配给A。 C不会发生什么事

        7
  •  2
  •   Lightness Races in Orbit    14 年前

    a的值将等于b,因为逗号运算符的优先级低于赋值运算符。

        8
  •  2
  •   Roopam    11 年前

    是逗号运算符的优先级低于赋值运算符

    #include<stdio.h>
    int main()
    {
              int i;
              i = (1,2,3);
              printf("i:%d\n",i);
              return 0;
    }
    

    输出:i=3
    因为逗号运算符总是返回最右边的值。
    如果逗号运算符带有赋值运算符:

     int main()
    {
          int i;
          i = 1,2,3;
          printf("i:%d\n",i);
          return 0;
    }
    

    Ouput:我=1
    如我们所知,逗号运算符的优先级低于赋值…

        9
  •  -2
  •   Community Mohan Dere    9 年前

    首先要做的是: 逗号实际上不是一个运算符,对于编译器来说,它只是一个有意义的标记。 在上下文中 其他代币。

    这意味着什么?为什么要麻烦?

    例1:

    为了理解同一个标记在不同上下文中的含义之间的差异,我们来看一个示例:

    class Example {
       Foo<int, char*> ContentA;
    }
    

    通常C++初学者会认为这个表达式可以比较事物,但它绝对是错误的。 < , > , 令牌取决于使用上下文。

    上面例子的正确解释当然是模板的一个实例。

    例2:

    当我们编写一个具有多个初始化变量和/或多个表达式的典型for循环时,我们也使用逗号:

    for(a=5,b=0;a<42;a++,b--)
       ...
    

    逗号的含义取决于使用上下文,这里是 for 建设。

    逗号在上下文中的实际含义是什么?

    更复杂的是(通常在C++中)逗号运算符本身可以重载(感谢 Konrad Rudolph 为了指出这点)。

    回到问题上来,代码

    a = b, c;
    

    对编译器的意义类似于

    (a = b), c;
    

    因为 priority = 令牌/运算符高于 , 令牌。

    这在上下文中被解释为

    a = b;
    c;
    

    (注意,解释取决于上下文,这里既不是函数/方法调用,也不是模板实例。)

    推荐文章