这个C/C++语句在理论上有什么问题(如果有的话):
*memory++ = BIT_MASK & *memory;
其中BIT_MASK
是一个任意的按位AND
掩码,而memory则是指针。
意图是读取内存位置,将值与掩码进行AND
运算,将结果存储在原始位置,最后将指针增加到下一个内存位置。
这个C/C++语句在理论上有什么问题(如果有的话):
*memory++ = BIT_MASK & *memory;
其中BIT_MASK
是一个任意的按位AND
掩码,而memory则是指针。
意图是读取内存位置,将值与掩码进行AND
运算,将结果存储在原始位置,最后将指针增加到下一个内存位置。
memory
两次(一次读取,一次写入),没有中间的序列点,并且语言标准没有指定增量将何时发生。(你可以多次读取同一内存;问题出现在尝试将一些写入与读取混合的情况下,如你的例子。)*memory++ &= BIT_MASK;
为了达到你想要的效果而不产生未定义行为,在C标准(ISO/IEC 9899:1999,也称为C99)中,第6.5节“表达式”中的第2段规定:
在前一个和下一个序列点之间,对象通过求值表达式最多仅修改一次其存储值。此外,先前的值只能读取以确定要存储的值。70)
这是C标准中的主要来源。脚注如下:
该段使语句表达式变得未定义,例如
i = ++i + 1; a[i++] = i;
同时允许
此外,“附录C(信息性)序列点”对所有这些进行了广泛讨论。
i = i + 1; a[i] = i;
您会在C ++标准中找到类似的措辞,但我不确定它是否有“附录C”的类比。
由于您在同一语句中使用了memory++
和memory
,因此这是未定义的行为。
这是因为C/C++没有明确指定++
将在何时发生。它可以在评估*memory
之前或之后发生。
以下是两种修复方法:
*memory = BIT_MASK & *memory;
memory++;
*memory++ &= BIT_MASK;
int i = 0; a[i++] = i;
,它将在索引0处存储值1。 - fredoverflow
*memory &= BIT_MASK; ++memory;
- Benjamin Lindley*memory
,而在于两次引用memory
。 - Oliver Charlesworth