【问题标题】:Comma operator and void expression逗号运算符和 void 表达式
【发布时间】:2011-07-21 00:57:04
【问题描述】:

我遇到了这段代码 sn -p 1

int return_printChar1()
{
    // code
    // oops! no return statement
}
int return_printChar2()
{
    // code
    return printf("Return");
}
int main()
{  
   int i;
   // some more code
   i = return_printChar2();
   if((return_printChar1(),i))
   {
      printf ("Gotcha");
   }
}

1:这不是现实生活中的例子。

我的问题是“代码 sn-p 的行为是否在 C 和 C++ 中定义良好?

我的看法:

在 C 中,行为是明确定义的,因为 6.5.17

逗号运算符的左操作数被评估为 void 表达式;求值后有一个序列点

在 C++03 中,这种行为是明确定义的,因为 5.18

以逗号分隔的一对表达式从左到右进行计算,左侧表达式的值丢弃

但是 C++03(6.6.3 部分)也这么说

从函数末尾流出相当于没有值的返回;这会在返回值的函数中导致未定义的行为。

在 C 中也是如此

如果控制到达非 void 函数(main() 除外)的结尾 (}),则行为未定义。

因此,考虑到所有这些点,我无法判断实际行为。大家怎么看?

P.S:如果你认为这个问题没用,而且你还有更好的事情要做,请自助:D.

【问题讨论】:

  • 其他人所说的......并且调用范围内没有原型的可变参数函数会调用未定义的行为。
  • @pmg :假设已包含必要的标头。 :)

标签: c++ c undefined-behavior comma-operator


【解决方案1】:

这是未定义的行为。

对左表达式的求值会导致返回值函数的末尾没有返回。仅仅因为该值被丢弃并不意味着评估从未发生过。

【讨论】:

    【解决方案2】:

    这显然是未定义的。 C99 §6.3.2.2 说,“(评估一个 void 表达式的副作用。)”因此该函数被评估并最终流出。没有出狱卡。

    【讨论】:

    • 在 C99 中从末端流出不会导致 UB 本身
    【解决方案3】:

    我拥有的 C 规范 (C99 TC3) 说

    如果到达终止函数的 },并且调用者使用了函数调用的值,则行为未定义。

    被称为“被评估为 void 表达式”的表达式的值被丢弃。所以在 C 的情况下,没有未定义的行为。在旧 C 中可能有所不同(如果我没记错的话,有些细节是)。

    C++ 的情况与 C 稍有不同,因为 C++ 支持将构造函数和析构函数作为返回值的类对象,并且不能保证它们在未初始化的内存上运行良好。也许这促成了 C++ 的不同规则。

    【讨论】:

    • 这就是我想知道的。在这方面,C 和 C++ 的行为有区别吗?如果是,为什么会有这样的差异?有什么历史原因吗?
    • @Prasoon 因为 C++ 有析构函数和构造函数,所以他们不能只说“哦,只有在调用者中使用返回值时它是 UB”。我猜他们只是不想保持这种 C 方式,并使其无条件地未定义(而不是只为类返回类型使其未定义)。
    猜你喜欢
    • 2019-02-07
    • 2019-04-25
    • 2017-01-23
    • 2013-11-22
    • 1970-01-01
    • 2010-10-04
    • 2017-07-11
    • 2010-12-16
    • 1970-01-01
    相关资源
    最近更新 更多