C和C+的差异+;具有序列点和UB 我用这个帖子来记录C程序中的未定义行为(UB),并指出我的代码< C和C++有自己的发散规则,用于[序列点] < /C>。那么C++和C++在序列点和相关的UB上有什么区别呢?我不能用一个关于C++序列的帖子来分析C代码中发生了什么吗?
*当然,我不是说C和C+的差异+;具有序列点和UB 我用这个帖子来记录C程序中的未定义行为(UB),并指出我的代码< C和C++有自己的发散规则,用于[序列点] < /C>。那么C++和C++在序列点和相关的UB上有什么区别呢?我不能用一个关于C++序列的帖子来分析C代码中发生了什么吗?,c++,c,language-lawyer,undefined-behavior,sequence-points,C++,C,Language Lawyer,Undefined Behavior,Sequence Points,*当然,我不是说C++的特性不适用于C这个问题有两个部分,我们可以轻松地比较序列点规则。这并没有使我们太远,C和C++是不同的语言,它们有不同的标准(几乎是两倍大),即使C++使用C作为标准参考,引用C的C++标准是错误的,反之亦然,不管某些部分是多么相似。C++标准明确地引用了C标准,但对于小的部分是这样的。 第二部分是C与C++的比较,可以有一些较大的差异,列举出所有未定义行为的差异可能是不可能的,但我们可以给出一些指示性的例子。 序列点 因为我们正在讨论的是C++11和C11之前的版本。就
C++
的特性不适用于C
这个问题有两个部分,我们可以轻松地比较序列点规则。这并没有使我们太远,C和C++是不同的语言,它们有不同的标准(几乎是两倍大),即使C++使用C作为标准参考,引用C的C++标准是错误的,反之亦然,不管某些部分是多么相似。C++标准明确地引用了C标准,但对于小的部分是这样的。
第二部分是C与C++的比较,可以有一些较大的差异,列举出所有未定义行为的差异可能是不可能的,但我们可以给出一些指示性的例子。
序列点
因为我们正在讨论的是C++11和C11之前的版本。就我所知,C99和C++11之前的草案标准之间的序列点规则没有太大差异。正如我们将在我给出的一些不同未定义行为的示例中看到的,序列点规则在其中不起作用
序列点规则在1.9
程序执行一节中介绍,其中说明:
- 每个完整表达式的评估完成时有一个序列点12)
- 调用函数时(无论函数是否为内联函数),在对所有函数求值之后都有一个序列点 在执行函数体中的任何表达式或语句之前发生的函数参数(如果有)李>
- 在复制返回值之后和执行外部任何表达式之前,还有一个序列点 功能(13)。C++中的几个上下文导致函数调用的评估,即使没有相应的函数调用。 语法出现在翻译单元中。[示例:对新表达式的求值调用一个或多个分配和 构造函数;参见5.3.4。另一个例子是,在上下文中可能会调用转换函数(12.3.2) 其中没有出现函数调用语法。-结束示例]序列指向函数入口和函数出口 (如上所述)是经过计算的函数调用的特性,无论调用 功能可能是
- 在计算每个表达式时
使用这些表达式(5.14、5.15、5.16、5.18)中运算符的内置含义,后面有一个序列点 第一个表达式的评估14)a && b a || b a ? b : c a , b
附录C
中的序列点列表,虽然它不是规范性的,但我发现与它引用的规范性章节没有任何分歧。它说:
以下是5.1.2.3中描述的序列点:
- 对参数求值后对函数的调用(6.5.2.2)
- 以下运算符的第一个操作数的结尾:逻辑AND&&(6.5.13); 逻辑或(6.5.14);有条件的(6.5.15); 逗号,(6.5.17)
- 完整声明符的结尾:声明符(6.7.5)李>
- 完整表达式的结尾:初始值设定项(6.7.8);表达式中的表达式 声明(6.8.3);选择语句的控制表达式(if或switch) (6.8.4); while或do语句的控制表达式(6.8.5);每个 声明的表述(6.8.5.3);返回语句中的表达式 (6.8.6.4)
以下条目在C++标准草案中似乎没有等价物,但这些来自C标准库,C++中引用了:
- 在库函数返回之前(7.1.4)
- 与每个格式化输入/输出函数转换关联的操作之后 说明符(7.19.6、7.24.2)
- 在每次调用比较函数之前和之后,以及 在对比较函数的任何调用和对象的任何移动之间 作为参数传递给该调用(7.20.5)
5
Expression一节中涉及的那些在序列点内多次修改变量的示例,我无法给出一个未定义但另一个未定义的示例。C99中说:
在上一个序列点和下一个序列点之间,对象应具有
通过计算
表达式72)此外,先前值应仅读取至
确定要存储的值。73)
它提供了以下示例:
i = ++i + 1;
a[i++] = i;
i = v[i ++]; / / the behavior is undefined
i = ++ i + 1; / / the behavior is undefined
在C++中,它表示:
除非另有说明,否则单个操作数的计算顺序
单个表达式的运算符和子表达式,以及顺序
在哪种情况下会产生副作用,目前尚不清楚
上一个和下一个序列点应存储标量对象的
通过表达式求值最多修改一次的值。
此外,只能通过访问先验值来确定
要存储的值。应满足本段的要求
对于完整表达式的子表达式的每个允许顺序
表达方式;否则,行为是未定义的
并提供以下示例:
i = ++i + 1;
a[i++] = i;
i = v[i ++]; / / the behavior is undefined
i = ++ i + 1; / / the behavior is undefined
在C++11和C11中,我们有一个主要的区别