[英]Differences in C and C++ with sequence points and UB
我使用这篇文章未定义的行为和序列点来记录C程序中的未定义行为( UB ),并且我指出C and C++ have their own divergent rules for this [sequence points]
。 那么当涉及到序列点和相关的UB时, C和C ++之间有什么区别? 我不能使用关于C ++序列的帖子来分析C代码中发生的事情吗?
*当然我不是在谈论不适用于C
的C++
特性。
这个问题有两个部分,我们可以毫不费力地解决序列点规则的比较。 这并不让我们虽然太远,C和C ++是具有不同标准的不同的语言( 在最新的C ++标准几乎是两倍于中大最新的C标准 ),而且即使C ++使用C作为规范性引用这将是不正确引用C的C ++标准,反之亦然,无论某些部分有多相似。 C ++标准确实引用了C标准,但这适用于小部分。
第二部分是C和C ++之间未定义行为的比较,可能存在一些重大差异,并且枚举未定义行为中的所有差异可能是不可能的,但我们可以给出一些指示性示例。
序列点
由于我们讨论的是序列点,所以这涵盖了C ++ 11之前和C11之前的版本。 就C99和Pre C ++ 11草案标准而言,序列点规则没有太大差别。 正如我们将在一些示例中看到的,我给出了不同的未定义行为,序列点规则不会在其中起作用。
序列点规则包含在C ++ 03第1.9
节最接近的草案C ++标准中。 程序执行说:
在评估每个表达式时
a && b a || b a ? b : c a , b
使用这些表达式(5.14,5.15,5.16,5.18)中的运算符的内置含义,在评估第一个表达式14)之后有一个序列点。
我将使用C99标准Annex C
草案中的序列点列表,虽然它不是规范性的,但我发现它与它所引用的规范性部分没有异议。 它说:
以下是5.1.2.3中描述的序列点:
以下条目似乎没有C ++标准草案中的等价物,但它们来自C标准库,C ++通过引用合并:
所以C和C ++之间没有太大的区别。
未定义的行为
当涉及到序列点和未定义行为的典型示例时,例如第5
节中涉及在序列点中多次修改变量的表达式 ,我无法想出一个未定义的示例,但不是其他。 在C99中它说:
在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的计算修改一次。 72)此外,先前值应只读以确定要存储的值。 73)
它提供了以下示例:
i = ++i + 1;
a[i++] = i;
在C ++中它说:
除非另有说明,否则单个运算符的操作数和各个表达式的子表达式的评估顺序以及副作用发生的顺序是未指定的.57)在前一个和下一个序列点之间,标量对象应该修改其存储值最多一次通过表达式的评价。 此外,只能访问先前值以确定要存储的值。 对于完整表达式的子表达式的每个允许排序,应满足本段的要求; 否则行为未定义
并提供以下示例:
i = v[i ++]; / / the behavior is undefined
i = ++ i + 1; / / the behavior is undefined
在C ++ 11和C11中,我们确实有一个主要的区别,这在C11表达式中的赋值运算符排序中有所涉及,如下所示:
i = ++i + 1;
这是因为即使排序规则相同,预增量在C ++ 11中也是左值 ,但在C11中不是。
我们在与序列点无关的区域确实存在重大差异:
可能有更多的例子,但这些是我之前写过的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.