如果(a)b=c,d=e,return;,为什么不编译

Why exactly this will not compile if (a) b = c, d = e, return;?

本文关键字:return 编译 为什么不 如果      更新时间:2023-10-16

我沉迷于"braceles"if,比如:

if (a) b++, c++, d = e; 

但有一件烦人的事情是return不能成为最后一部分的一部分。凭直觉,我感觉到了为什么,但有人能用编程语言解释为什么这不会编译吗?

main() {
int a, b, c, d, e;
if (a) b = c, d = e, return;
}

如果你介意的话,也请解释为什么会这样设计,这对我来说似乎是一个缺陷。我可以用C语言理解,但在C++中,它本可以重新设计,而不会与现有的C代码产生重大兼容性损失。

只是为了比较:这些将编译并做预期的事情:

while (a < 10) a++, b--, c += 2;
while (a < 10) if (a == 5) half = a, save();

"逗号"运算符就是一个运算符。它的左侧和右侧必须是表达式,而return不是表达式。

为了详细说明,逗号运算符首先计算其左侧,然后丢弃该值。然后,它计算其右侧,整个逗号表达式计算为右侧的值。

与此类似:

template <typename T, typename U>
U operator,(T t, U u)
{
return u;
}

因此,不能在逗号表达式中放入任何不是表达式本身的内容。

如果您希望同时执行一系列语句并将它们分组在一起,那么;{}就是这样做的。没有理由在逗号运算符中重复这种行为。

可以通过以下方式完成

if (a) return ( b = c, d = e, 0 );

Oe如果没有返回表达式

if (a) return ( b = c, d = e, ( void )0 );

这是否回答了OP真正提出的问题,这可能是一个悬而未决的问题,但如果有人关心为什么逗号运算符是这样设计的,我认为它可以追溯到BCPL。

在BCPL中,您可以组合一系列任务,如:

L1 := R1
L2 := R2

转换为单个语句(命令),如:

L1, L2 := R1, R2

就像在C和C++中一样,这些都是按从左到右的顺序执行的。与C和C++不同,这个"逗号运算符"没有生成一个表达式(至少在C使用这个术语时是这样)。

BCPL还有一个resultis,它可以让你把一组语句变成一个函数。

至少在我看来,在C中,Dennis1决定将这两个概念组合成一个更简单的概念:一个逗号运算符,可以连续计算多个表达式,并产生一个结果。

参考:BCPL参考手册


  1. 我想公平地说,我应该提到这个决定实际上是由Ken Thomson在B的设计中做出的。关于B的文件很少,几乎无法猜测

如前所述,return不是一个表达式,而是一个关键字。然而,b = c, d = e是一个表达式。因此,您的意图可能是:

if (a) return (b = c, d = e, 0);

b = c, d = e, return实际上没有任何意义,因为它与逗号运算符在其他上下文中的工作方式不一致。想象一下,如果你能做到这一点:

for (int i = 0, j = 0, return; ...

这完全没有道理。如果return在此上下文中有意义,那么它也是多余的,因为逗号运算符已经返回其最后一个操作数。也没有意义,因为逗号运算符已经计算了其操作数,那么return something在这种情况下会有什么好处呢?

查看代码的人可能会瞥一眼代码,然后说:"这应该是:if (a) (b = c, d = e); return 0;",这是一个陷阱,因为缺少大括号。它们的真正含义是if (a) { (b = c, d = e); return 0; },但如果您使用此答案顶部提到的语法,则可以避免此问题。它根本不可读,因为它没有语义意义。

无论如何,只有当bd是全局变量时,这才有意义,例如errno,允许您分配给变量并在一条语句中返回。

如果(a)b=c,d=e,return;,为什么不编译;?

这是因为逗号(,)运算符的左操作数和右操作数必须是表达式return语句不是表达式。参见C和C++标准为,运算符定义的语法:

C11:6.5.17逗号运算符

Syntax
expression:
assignment-expression
expression , assignment-expression

C++标准定义了相同的语法

C++:5.18逗号运算符[expr.Comma]

逗号运算符从左到右分组。

expression:
assignment-expression
expression , assignment-expression  

用逗号分隔的一对表达式1从左到右求值;

请注意,标准规定了表达式return不是表达式。


1.重点是我的

我在C中可以理解,但在C++中,如果没有与现有C代码的主要兼容性损失。

它本来可以,但为什么会有人希望它是?该语言已经包含了一种达到目的的方法——大括号。它们比像您那样滥用逗号运算符更可靠、更有用。例如,如果您正在使用UDT,那么当我重载逗号运算符时,您将遇到一些令人讨厌的意外。哎呀!

更重要的是,将return作为表达式是没有意义的,因为函数在求值时已经返回,所以任何人都不可能使用任何假设的返回值。

你的整个问题都是基于你个人对牙套的厌恶。没有其他设计语言的人真的有这种感觉。