19

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

int a = (1, 2, 3);

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

4

6 回答 6

37

这是逗号运算符:评估a, b首先导致a要评估的原因,然后b是 ,结果是 的结果b

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

于 2013-05-15T11:00:21.597 回答
19

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

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

另一个有趣的用例是,为了清楚和简洁起见,尝试将多个概念相关的表达式放入单个语句(如 return)时,例如在具有frexp怪异指针返回参数的 good old 的实现中(忽略正确的事实C++ 只会返回一对):

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

这比同等的更精简

double frexp(double arg, int *exp)
{
    if(...)
    {
        *exp = ...;
        return result;
    }
    ...
}
于 2013-05-15T11:00:04.067 回答
7

Wiki:逗号运算符

i = (a, b, c);          // stores c into i
于 2013-05-15T10:59:47.030 回答
5

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

C11标准6:5:17

逗号运算符

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

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

于 2013-05-15T11:12:58.930 回答
3

它只计算 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++ 中的工作方式相同

于 2013-05-15T11:04:46.990 回答
3

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

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

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

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

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

于 2013-05-15T11:14:54.423 回答