【问题标题】:What does a comma separated list of values, enclosed in parenthesis mean in C? a = (1, 2, 3); [duplicate]用括号括起来的逗号分隔值列表在 C 中是什么意思? a = (1, 2, 3); [复制]
【发布时间】:2013-05-09 22:01:46
【问题描述】:

我刚刚遇到了基本上执行以下操作的代码:

int a = (1, 2, 3);

我以前从未见过这种符号。什么意思?

【问题讨论】:

  • 浪费了输入代码。 3 分配给 a。
  • L1, L2, L3.. 还有更多:-) 哇 11 和越来越多的支持:-)
  • 昨天当我问了一个简单的问题时,我得到了一连串的反对票!!上帝可以这么不公平!!
  • 18 票赞成可能与其他数百个问题重复的问题...嗯...
  • 如果你真的不知道它叫做逗号运算符,那么在 Google/SO 中很难搜索到它。因此,您必须尝试在搜索查询中描述语法。尽管这个问题确实是重复的,但我想这对于那些不知道运算符被称为什么并试图通过描述语法来寻找答案的人来说是有价值的,这就是我想要做的。

标签: c++ c comma


【解决方案1】:

维基:Comma operator

i = (a, b, c);          // stores c into i

【讨论】:

    【解决方案2】:

    它使用comma operator,它只是按顺序计算每个操作数表达式(在它们之间引入适当的序列点)并返回最后一个。因此,您的示例实际上等同于int a = 3;

    但它确实是 CC++ 中使用最少的运算符之一,不要与函数调用表达式、初始值设定项列表等中使用的逗号混淆其他地方。一个不太罕见的用例是 for 循环中的多个增量 (for(...; ...; ++i,++j)),尽管您可能从未想过实际上使用所谓的逗号运算符。

    另一个有趣的用例是为了清晰和简洁而尝试将多个概念上相关的表达式放入单个语句(如返回),就像在旧的 frexp 的实现中,它带有奇怪的指针返回参数(忽略正确的 C++ 只会返回一对的事实):

    double frexp(double arg, int *exp)
    {
        if(...)
            return *exp=..., result;
        ...
    }
    

    比同类产品更精简

    double frexp(double arg, int *exp)
    {
        if(...)
        {
            *exp = ...;
            return result;
        }
        ...
    }
    

    【讨论】:

    • 实际上,我比 hvd 目前票数最高的答案更喜欢这个答案,但我与互联网争论的是谁? :)
    • @ChristianRau 记住this,您可以在此处使用逗号并显示示例:-)
    • @Koushik 哈哈,对!仍然很奇怪,但比?: 版本好。我仍然不会在这个答案中展示它,因为我认为它并不是一个真正合理的用例。但是 +1 以获得有趣的交叉引用。
    • 是的,比 ?: 好得多,是的,你的答案是完整的。
    【解决方案3】:

    这是comma operator:评估a, b首先导致a被评估,然后是b,结果是b的结果。

    int a = (1, 2, 3); 首先计算1,然后是2,最后是3,并使用最后一个3 来初始化a。在这里没用,但是当,的左操作数有副作用时(通常:当它是一个函数调用时)它会很有用。

    【讨论】:

    • 通常我把它写成({ doSomething(); x; }),这对于使用临时结果的宏定义特别方便。除了我使用分号而不是逗号来分隔这些(子)表达式之外,这些符号之间有什么区别吗?
    • @leemes 这在标准 C 和 C++ 中是无效的,但它被一些编译器(至少是 GCC)接受为允许使用语句的扩展,而不仅仅是表达式,这样你就可以做({ if (0) { 1; } 2; }).
    • “通常:当它是一个函数调用时”你能解释一下吗?我问是因为我对上下文感到困惑。你的意思是 foo(T,T2),this comma or foo(T),foo(T)?
    • this?怎么样
    • 更具体地说,用逗号分隔的表达式是从从左到右计算的。这种逗号表达式的结果是最右边表达式的值跨度>
    【解决方案4】:

    它只计算 1、2 和 3(因为它们只是值,但也可以是函数调用),并将最后一个的值(或返回值)设置为左侧操作数(在您的示例中,a )。

    也许这会帮助您了解它的工作原理:

    #include <stdio.h>
    
    int toto()
    {
      printf("toto()\n");
      return (21);
    }
    
    int tata()
    {
      printf("tata()\n");
      return (42);
    }
    
    int main()
    {
      int a = (toto(), tata());
      printf("%d\n", a);
      return (0);
    }
    

    输出:

    toto()
    tata()
    42
    

    编辑: Tha 的 C 代码,在 C++ 中也一样

    【讨论】:

    • 我冒昧添加了相应的输出。
    【解决方案5】:

    它是逗号运算符。 C11 标准讲述了这种运算符的一个用例。

    C11standard6:5:17

    逗号运算符

    逗号运算符的左操作数被评估为 void 表达;在它的评估和那个之间有一个序列点 的右操作数。然后对右操作数求值;结果 有它的类型和价值。114)

    逗号运算符(如所述 在本子条款中)不能出现在使用逗号的上下文中 列表中的单独项目(例如函数的参数或 初始化器)。另一方面,它可以在一个 带括号的表达式或在 a 的第二个表达式内 这种情况下的条件运算符。在函数调用中 f(a, (t=3, t+2), c) 函数有三个参数,第二个参数是 值 5。

    【讨论】:

      【解决方案6】:

      这是comma operator。它“包装”多个表达式,从左到右计算它们,整个表达式的值由最后一个子表达式确定。在您的示例中,它的计算结果为 3

      逗号运算符特别方便的情况是,如果您想在 for 循环“递增”表达式中执行多项操作,例如递增 两个 变量。

      示例:沿对角线迭代图像,使用 xy 作为单独的变量。我为xy 使用了两个单独的变量,因为我可能想在循环中独立地更改其中一个(请记住,这只是一个愚蠢的例子)。所以我想在for循环的“增量”语句中同时增加xy

      for(int x = 0, y = 0; x < width && y < height; ++x, ++y) {
          // ...                                     ^^^^^^^^
      }
      

      请注意,for循环的“初始化”表达式使用逗号运算符;它只是声明了两个变量。

      【讨论】:

      • 我宁愿把第一句中的"separator"改为"operator",因为前者宁愿是我所说的通常(非操作员)使用逗号。但是很好,您指出了 for 循环的初始化表达式的区别。
      • 糟糕,这无论如何都是偶然的。感谢您指出;)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多