void RemoveSpaces(char* source)
{
char* i = source;
char* j = source;
while(*j != 0)
{
*i = *j++; // UB?
if(*i != ' ')
i++;
}
*i = 0;
}
我的第一反应是,这段代码会引发未定义的行为,因为 i
和 j
指向同一内存位置,表达式 *i = *j++;
将访问同一变量两次,而不是用于确定要存储什么,中间没有序列点。尽管它们是两个不同的变量,但最初它们指向同一内存位置。
然而,我不确定,在实践中,两个非序列化访问同一内存位置如何会造成任何伤害。
我是否正确地陈述了这是未定义的行为?如果是,那么有没有任何依赖于此类 UB 的示例可以导致有害行为?
编辑
将此标记为 UB 的 C 标准的相关部分是:
C99 6.5
在前一个和后一个序列点之间,对象通过计算表达式的值最多被修改一次其存储的值。此外,只能读取先前的值以确定要存储的值。
C11 6.5
如果标量对象上的副作用相对于同一标量对象上的不同副作用或使用相同标量对象的值计算是无序的,则行为未定义。如果表达式的子表达式有多个允许的排序方式,则如果在任何排序中发生这样的无序副作用,则行为未定义。
文本的实际含义应该在标准的两个版本中相同,但我认为 C99 文本更易于阅读和理解。
*j
(与*i
相同)已被读取并分配给*i
,而*j
的递增是在赋值完成后进行的,因此这是一种定义良好的行为。我理解得对吗? - Natasha Duttaj
(指针地址)而不是*j
(指针所指向的内容)。 - Lundin