gpt4 book ai didi

c - 访问同一个内存位置两次,UB 与否?

转载 作者:太空狗 更新时间:2023-10-29 14:56:02 26 4
gpt4 key购买 nike

this thread评分最高的答案获得了很多赞成票,甚至还获得了赏金。提出如下算法:

void RemoveSpaces(char* source)
{
char* i = source;
char* j = source;
while(*j != 0)
{
*i = *j++; // UB?
if(*i != ' ')
i++;
}
*i = 0;
}

我的下意识 react 是这段代码调用了未定义的行为,因为 ij 指向相同的内存位置,并且像 *i 这样的表达式= *j++; 然后会访问同一个变量两次,用于确定要存储什么的其他目的,其间没有序列点。尽管它们是两个不同的变量,但它们最初指向相同的内存位置。

但是我不确定,因为我不太明白对同一内存位置的两次非顺序访问在实践中如何造成任何伤害。

我说这是未定义的行为是否正确?如果是这样,是否有任何示例说明依赖此类 UB 会如何导致有害行为?


编辑

将此标记为 UB 的 C 标准的相关部分是:

C99 6.5

Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.

C11 6.5

If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.

文本的实际含义在标准的两个版本中应该是相同的,但我相信 C99 文本更容易阅读和理解。

最佳答案

有两种情况,在没有中间序列点的情况下访问同一个对象两次是未定义的行为:

  1. 如果修改同一个对象两次。例如

    int x = (*p = 1, 1) + (*p = 2, 100);

    显然你不知道 *p 是 1 还是 2,但 C 标准中的措辞表明它是未定义的行为,即使你写

    int x = (*p = 1, 1) + (*p = 1, 100);

    所以存储相同的值两次并不能拯救你。

  2. 如果修改了对象,还要读取它,而不是使用读取的值来确定对象的新值。这意味着

    *p = *p + 1; 

没问题,因为你读取了 *p,你修改了 *p,但是你读取了 *p 以确定存储的值进入*

关于c - 访问同一个内存位置两次,UB 与否?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30375896/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com