【问题标题】:How are complicated expression using the comma operator parsed in C?在 C 中如何使用逗号运算符解析复杂的表达式?
【发布时间】:2018-03-23 18:25:22
【问题描述】:

阅读以下两篇后...

What does the comma operator , do?

How does the Comma Operator work

我仍然不确定我是否无法解析我在别人的源代码中找到的以下语句:

int i, n, val, locala = a, bestval = -INFINITY;

逗号运算符按从左到右的顺序计算,是吗?如果我们使用括号来显示优先顺序,我认为我们有这样的事情:

(int i, (n, (val, (locala = a, (bestval = -INFINITY)))));

那么,也许,原文就相当于下面的?

int bestval = -INFINITY;
int locala = a;
int val;
int n;
int i;

如果是这样,为什么int 关键字应用于所有变量而不是仅应用于最左边的变量i

另外,最右边的表达式返回它们的值,是吗?因此,locala = a 可能会在分配发生后返回 locala 的值。这是否意味着变量inval 都被初始化了?如果是这样,它们会被初始化为什么? -INFINITY? a的值?

【问题讨论】:

  • 那不是逗号操作符。 C 中逗号的大多数用法不是逗号运算符。
  • 体面的经验法则:如果左边的东西没有被丢弃,那不是逗号运算符。
  • @Toothpick Anemone 没有逗号运算符。有一个声明清单。
  • @KrassiEm:这不是一些超深奥的不切实际的构造。提问者试图理解真实的代码,他们以一种非常自然的方式误解了它。
  • @KrassiEm 解析问题和语言律师问题在这里不是题外话。如果你个人不是在寻找这样的问题,你为什么还要阅读它?标题应该足以阻止你。

标签: c variable-assignment comma assignment-operator comma-operator


【解决方案1】:

逗号标记在 C 中做了几个不同的事情,不应该混淆:

  • 分离类似函数的预处理器宏定义的参数:

    #define CAT_NO_EXPAND(x,y) x ## y
    
  • 分离函数式预处理器宏使用的参数:

    int CAT_NO_EXPAND(ident_, 3) = 3;
    
  • 在枚举定义中分隔枚举数:

    enum colors { RED, GREEN, BLUE };
    
  • 在声明中分隔声明符:

    int a, b=3, c;
    
  • 在大括号初始化器中分隔成员/元素:

    int arr[3] = {0, 2, 4};
    struct mystruct s = {8, 3.0};
    func( (mystruct s){8, 3.0} );
    
  • 分隔函数声明或定义的参数:

    void f(int n, double, const char* fmt, ...);
    
  • 分隔函数调用表达式的参数:

    f(3, 0.5, "Test %s\n", "Hello");
    
  • 形成一个表达式,如果评估将丢弃左侧并使用右侧的值作为其值。

    #define CALL_G_IGNORE_RESULT(x) ((void)g(x), 0)
    for (i=0, j=0; i<m && j<n; ++i, ++j)
    

您所读到的有关“逗号运算符”的内容描述了最后一种情况,该情况适用于与上述任何其他情况都不匹配的表达式上下文。

您发布的是一个声明,它不涉及“逗号运算符”,只是一次声明多个变量。任何初始化程序都按顺序计算(这很重要,因为您可以在以后的初始化程序中使用较早声明的变量)。

【讨论】:

  • 您可以在列表项中将代码块再缩进 4 个空格,以使其看起来更好
  • @AnttiHaapala 我通常会这样做,但 SO 似乎在项目符号列表项之后立即出现代码问题。
  • 空间就像暴力,如果它们不起作用,你只是没有使用足够的空间。
【解决方案2】:
  1. 这不是逗号运算符。
  2. 这是一个声明列表。
  3. 它从左到右执行,或者至少它的可执行部分是。
  4. 求值顺序和运算符优先级是两个不同的东西。
  5. 从左到右的执行顺序与括号中的内容相反。
  6. int 关键字应用于所有声明,因为这就是语法的含义。
  7. 这里没有“最右边的表达式”,只有带有初始值设定项的声明。
  8. 因此也没有返回值。
  9. inval 未初始化。

【讨论】:

    【解决方案3】:

    这个

    int i, n, val, locala = a, bestval = -INFINITY;
    

    是一个声明。

    声明在 C 中定义如下(不包括所有细节)

    declaration:
        declaration-specifiers init-declarator-listopt ;
    
    init-declarator-list:
        init-declarator
        init-declarator-list , init-declarator
    
    init-declarator:
        declarator
        declarator = initializer
    

    declaration-specifiers 影响 init-declarator- 中的所有声明符 列表

    如果你想在声明中使用逗号运算符,那么这样的声明可以看起来像

    int i = 1, j = 2, k = ( ++i, j++, i + j );
    

    这里的表达式( ++i, j++, i + j ) 用作基于逗号运算符的初始化器。

    声明后i 等于2j - 3k - 5

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-21
      • 2019-02-07
      • 2013-11-22
      • 1970-01-01
      • 2020-10-11
      • 2018-02-20
      • 2019-04-25
      • 1970-01-01
      相关资源
      最近更新 更多