我使用这篇文章Undefined Behavior and Sequence Points来记录 C 程序中的未定义行为( UB ),并向我指出C and C++ have their own divergent rules for this [sequence points]
。那么当涉及到序列点和相关的 UB 时, C 和 C ++ 之间有什么区别?我不能使用关于 C ++ 序列的帖子来分析 C 代码中发生的事情吗?
*当然我不是在谈论C++
不适用于C
的功能。
答案 0 :(得分:4)
这个问题有两个部分,我们可以毫不费力地解决序列点规则的比较。这并没有让我们走得太远,C和C ++是不同的语言,它们有不同的标准( latest C++ standard几乎是latest C standard 的两倍)尽管C ++使用C作为规范性引用,引用C的C ++标准是错误的,反之亦然,无论某些部分有多相似。 C ++标准确实引用了C标准,但这适用于小部分。
第二部分是C和C ++之间undefined behavior的比较,可能存在一些重大差异,并且列举未定义行为的所有差异可能是不可能的,但我们可以给出一些指示性示例。
序列点
由于我们正在谈论sequence points,所以这涵盖了预C ++ 11和前C11。就C99和Pre C ++ 11草案标准而言,序列点规则没有太大差别。正如我们将在一些示例中看到的,我给出了不同的未定义行为,序列点规则不会在其中起作用。
序列点规则包含在closest draft C++ standard to C++03部分1.9
程序执行中,其中包含:
在每个表达式的评估中
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中,我们确实有一个主要区别,Assignment operator sequencing in C11 expressions涵盖了以下内容:
i = ++i + 1;
这是因为即使排序规则相同,C ++ 11中的预增量为左值,但在C11中则不然。
我们在与序列点无关的区域确实存在重大差异:
可能有更多的例子,但这些是我之前写过的。