指针和自增后操作

Pointer and post-increment funny business

本文关键字:操作 指针      更新时间:2023-10-16

这个c/c++语句在理论上有什么问题?

*memory++ = BIT_MASK & *memory;

其中BIT_MASK为任意位AND掩码,内存为指针。

目的是读取内存位置,AND值与掩码,存储结果在原始位置,然后最后增加指针指向下一个内存位置。

您正在调用未定义的行为,因为您在没有中间序列点的单个语句中引用memory两次(一次用于读取,一次用于写入),并且语言标准没有指定何时会发生增量。(你可以多次读取相同的内存;当您试图将一些书写与阅读混合在一起时,就会出现问题-就像您的示例一样。

你可以使用:

*memory++ &= BIT_MASK;

实现你想要实现的目标,而不会产生未定义的行为。


在C标准(ISO/IEC 9899:1999又名C99)中,§6.5 'Expressions',¶2表示

在前一个序列点和下一个序列点之间的是对象的存储值通过表达式的求值最多修改一次。进一步,先验值70)

这是C标准的主要来源。脚注说:

这个段落呈现未定义的语句表达式,如

i = ++i + 1;
a[i++] = i;

同时允许

i = i + 1;
a[i] = i;

此外,"附录C(信息性)序列点"对所有这些进行了广泛的讨论。

你会在c++标准中找到类似的措辞,尽管我不确定它是否有类似的"附录C"。

这是未定义的行为,因为您在同一语句中有memory++memory

这是因为C/c++没有指定++发生的确切时间。它可以在*memory求值之前或之后。

这里有两种方法来修复它:
*memory = BIT_MASK & *memory;
memory++;

或者直接:

*memory++ &= BIT_MASK;