相关疑难解决方法(0)

未定义的行为和序列点

什么是"序列点"?

未定义的行为和序列点之间的关系是什么?

我经常使用有趣和复杂的表达方式a[++i] = i;,让自己感觉更好.我为什么要停止使用它们?

如果您已阅读此内容,请务必访问后续问题重新加载未定义的行为和序列点.

(注意:这是Stack Overflow的C++常见问题解答的一个条目.如果你想批评在这种形式下提供常见问题解答的想法,那么发布所有这些的元数据的发布将是这样做的地方.这个问题在C++聊天室中受到监控,其中FAQ的想法一开始就出现了,所以你的答案很可能被那些提出想法的人阅读.)

c++ c++-faq undefined-behavior sequence-points

970
推荐指数
4
解决办法
10万
查看次数

序列点在c

命令式编程中的序列点定义了计算机程序执行中的任何点,在该点处保证先前评估的所有副作用都已执行,并且尚未执行后续评估的副作用.

这是什么意思?有人可以用简单的语言解释一下吗?

c sequence-points

29
推荐指数
3
解决办法
5863
查看次数

序列点来自哪里?

我知道写点东西

++a = a++;
Run Code Online (Sandbox Code Playgroud)

不仅是不可读的,而且还违反了c/c ++序列点.

这些限制来自哪里?在将它们视为错误之前,如何才能看到这些"问题"?

c c++ sequence-points

9
推荐指数
3
解决办法
2337
查看次数

C中的序列点和副作用

在这个C-FAQ中给出了序列点 ;

标准规定:
在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的计算来修改一次.此外,只能访问先前值以确定要存储的值.

在例子中

i = i++;
a[i] = i++;
Run Code Online (Sandbox Code Playgroud)

从声明的第一句可以清楚地看出,这些例子是未定义行为的结果.
在解释声明的第二句时,据说;

第二句话说:如果一个对象被写入一个完整的表达式,那么同一个表达式中对它的任何和所有访问都必须直接参与计算要写入的值.此规则有效地将法律表达式约束为在修改之前明显存在访问的表达式.例如,旧备用

 i = i + 1 
Run Code Online (Sandbox Code Playgroud)

是允许的,因为i的访问用于确定i的最终值.这个例子

a[i] = i++
Run Code Online (Sandbox Code Playgroud)

是不允许的,因为i的一个访问(a [i]中的一个)与最终存储在i中的值无关(在i ++中发生),因此没有好的方法来定义.

我的问题是;
1.它是什么意思,如果一个对象被写入一个完整的表达式,那么在同一个表达式中对它的任何和所有访问必须直接参与计算要写入的值.

2.它是什么意思,该示例a[i] = i++ 是不允许的,因为i的一个访问(a [i]中的一个)与最终存储在i中的值无关(在i ++中发生)
可能有人以一种简单的方式解释它吗?

c undefined-behavior sequence-points

6
推荐指数
2
解决办法
830
查看次数

序列点警告说明

我是 C 初学者。当我尝试运行以下代码时:

#include <stdio.h>

    int main(void) {

    int a = 3, b;

    b = printf("%d %d", a, a++);
    a = printf(" %d", b);
    printf(" %d", a);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它向我展示:

error: operation on 'a' may be undefined [-Werror=sequence-point]
b = printf("%d %d", a, a++);
                        ^
Run Code Online (Sandbox Code Playgroud)

但在这里我只改变了一次的值。那为什么会出现序列点错误呢?

我正在使用 -Wall -Werror 标志。

c sequence-points

2
推荐指数
1
解决办法
4191
查看次数

不是 a[i++] = 1 (一) 其中,增量的计算相对于数组的索引是无序的,导致违反 S6.5.2

问题长度字数限制..

正如@Karl Knechtel所指出的,我很困惑,是否获取相对于增量操作未排序的数组索引操作i++?如果它们没有排序,为什么 C 标准 6.5.2 行提到(强调添加到我理解的单词/短语中,适用于此处)

如果标量对象上的副作用 对于同一标量对象上的不同副作用或使用同一标量对象的值的值计算是无序的,则行为是未定义的。

我读了这个问题,我无法理解 C99 中的一些句子,其中 OP 试图理解为什么a[i++] = 1未定义。Pascal Cuoq已接受且得票最高的答案之一提到这是定义的行为。

-std=c99我还尝试使用,-Wall-Wextra标志以及一系列其他标志(基本上是 GCC 11.2.0 中启用的所有标志)来编译程序,但代码没有抛出任何警告

然而,我的问题/困惑是为什么这是一个定义的行为?

来自C11标准S6.5.2

如果标量对象上的副作用相对于同一标量对象上的不同副作用或使用同一标量对象的值的值计算是无序的,则行为是未定义的。如果表达式的子表达式有多个允许的排序,并且在任何排序中出现此类未排序的副作用,则行为未定义。

在阅读了 SO 上的大多数线程(带有标签[C][sequence-points])后,我的理解/推理是 i++ 会导致更新 i 值的副作用。在这种情况下,这个副作用不会被排序到使用相同缩放器对象的值计算。我的理解是a[integer object]构成value computation。那么,它应该是未定义的行为吗?

即使从 C99 S6.5(p2)

此外,应只读先前值以确定要存储的值。

我理解/解释这个表达式也应该呈现a[i++] = 1未定义?

c language-lawyer

1
推荐指数
1
解决办法
154
查看次数