[英]Differences in C and C++ with sequence points and UB
I used this post Undefined Behavior and Sequence Points to document undefined behavior( UB ) in a C program and it was pointed to me that C and C++ have their own divergent rules for this [sequence points]
. 我使用这篇文章未定义的行为和序列点来记录C程序中的未定义行为( UB ),并且我指出
C and C++ have their own divergent rules for this [sequence points]
。 So what are the differences between C and C++ when it comes to sequence points and related UB ? 那么当涉及到序列点和相关的UB时, C和C ++之间有什么区别? Can't I use a post about C++ sequences to analyze what is happening in C code?
我不能使用关于C ++序列的帖子来分析C代码中发生的事情吗?
* Of Course I am not talking about features of C++
not applicable to C
. *当然我不是在谈论不适用于
C
的C++
特性。
There are two parts to this question, we can tackle a comparison of sequence points rules without much trouble. 这个问题有两个部分,我们可以毫不费力地解决序列点规则的比较。 This does not get us too far though, C and C++ are different languages which have different standards( the latest C++ standard is almost twice as large as the the latest C standard ) and even though C++ uses C as a normative reference it would be incorrect to quote the C++ standard for C and vice versa, regardless how similar certain sections may be.
这并不让我们虽然太远,C和C ++是具有不同标准的不同的语言( 在最新的C ++标准几乎是两倍于中大最新的C标准 ),而且即使C ++使用C作为规范性引用这将是不正确引用C的C ++标准,反之亦然,无论某些部分有多相似。 The C++ standard does explicitly reference the C standard but that is for small sections.
C ++标准确实引用了C标准,但这适用于小部分。
The second part is a comparison of undefined behavior between C and C++, there can be some big differences and enumerating all the differences in undefined behavior may not be possible but we can give some indicative examples. 第二部分是C和C ++之间未定义行为的比较,可能存在一些重大差异,并且枚举未定义行为中的所有差异可能是不可能的,但我们可以给出一些指示性示例。
Sequence Points
序列点
Since we are talking about sequence points then this is covering pre C++11 and pre C11. 由于我们讨论的是序列点,所以这涵盖了C ++ 11之前和C11之前的版本。 The sequence point rules do not differ greatly as far as I can tell between C99 and Pre C++11 draft standards.
就C99和Pre C ++ 11草案标准而言,序列点规则没有太大差别。 As we will see in some of the example I give of differing undefined behavior the sequence point rules do not play a part in them.
正如我们将在一些示例中看到的,我给出了不同的未定义行为,序列点规则不会在其中起作用。
The sequence points rules are covered in the closest draft C++ standard to C++03 section 1.9
Program execution which says: 序列点规则包含在C ++ 03第
1.9
节最接近的草案C ++标准中。 程序执行说:
In the evaluation of each of the expressions 在评估每个表达式时
a && b a || b a ? b : c a , b
using the built-in meaning of the operators in these expressions (5.14, 5.15, 5.16, 5.18), there is a sequence point after the evaluation of the first expression14). 使用这些表达式(5.14,5.15,5.16,5.18)中的运算符的内置含义,在评估第一个表达式14)之后有一个序列点。
I will use the sequence point list from the draft C99 standard Annex C
which although it is not normative I can find no disagreement with the normative sections it references. 我将使用C99标准
Annex C
草案中的序列点列表,虽然它不是规范性的,但我发现它与它所引用的规范性部分没有异议。 It says: 它说:
The following are the sequence points described in 5.1.2.3:
以下是5.1.2.3中描述的序列点:
The following entries do not seem to have equivalents in the draft C++ standard but these come from the C standard library which C++ incorporates by reference: 以下条目似乎没有C ++标准草案中的等价物,但它们来自C标准库,C ++通过引用合并:
So there is not much of a difference between C and C++ here. 所以C和C ++之间没有太大的区别。
Undefined Behavior
未定义的行为
When it comes to the typical examples of sequence points and undefined behavior, for example those covered in Section 5
Expression dealing with modifying a variable more than once within a sequence points I can not come up with an example that is undefined in one but not the other. 当涉及到序列点和未定义行为的典型示例时,例如第
5
节中涉及在序列点中多次修改变量的表达式 ,我无法想出一个未定义的示例,但不是其他。 In C99 it says: 在C99中它说:
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression.
在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的计算修改一次。 72) Furthermore, the prior value shall be read only to determine the value to be stored.
72)此外,先前值应只读以确定要存储的值。 73)
73)
and it provides these examples: 它提供了以下示例:
i = ++i + 1;
a[i++] = i;
and in C++ it says: 在C ++中它说:
Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified.57) Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression.
除非另有说明,否则单个运算符的操作数和各个表达式的子表达式的评估顺序以及副作用发生的顺序是未指定的.57)在前一个和下一个序列点之间,标量对象应该修改其存储值最多一次通过表达式的评价。 Furthermore, the prior value shall be accessed only to determine the value to be stored.
此外,只能访问先前值以确定要存储的值。 The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression;
对于完整表达式的子表达式的每个允许排序,应满足本段的要求; otherwise the behavior is undefined
否则行为未定义
and provides these examples: 并提供以下示例:
i = v[i ++]; / / the behavior is undefined
i = ++ i + 1; / / the behavior is undefined
In C++11 and C11 we do have one major difference which is covered in Assignment operator sequencing in C11 expressions which is the following: 在C ++ 11和C11中,我们确实有一个主要的区别,这在C11表达式中的赋值运算符排序中有所涉及,如下所示:
i = ++i + 1;
This is due to the result of pre-increment being an lvalue in C++11 but not in C11 even though the sequencing rules are the same. 这是因为即使排序规则相同,预增量在C ++ 11中也是左值 ,但在C11中不是。
We do have major difference in areas that have nothing to do with sequence points: 我们在与序列点无关的区域确实存在重大差异:
There are probably plenty more examples but these are ones I have written about before. 可能有更多的例子,但这些是我之前写过的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.