gpt4 book ai didi

c++ - C 别名规则和 memcpy

转载 作者:IT老高 更新时间:2023-10-28 23:17:13 25 4
gpt4 key购买 nike

在回答另一个问题时,我想到了以下示例:

void *p;
unsigned x = 17;

assert(sizeof(void*) >= sizeof(unsigned));
*(unsigned*)&p = 17; // (1)
memcpy(&p, &x, sizeof(x)); // (2)

第 1 行打破了别名规则。但是,第 2 行是可以的。别名规则。问题是:为什么?编译器是否有关于 memcpy 等函数的特殊内置知识,或者是否有其他一些规则可以使 memcpy 正常?有没有办法在标准 C 中实现类似 memcpy 的函数而不破坏别名规则?

最佳答案

C 标准 对此非常清楚。 p 命名的对象的有效类型是 void* ,因为它有一个声明的类型,见 6.5/6 . C99 中的别名规则适用于读取 写入,以及写入void*。通过 unsigned (1) 中的左值根据 6.5/7 是未定义的行为.

相比之下,memcpy(2)很好,因为 unsigned char*可以为任何对象( 6.5/7 )设置别名。该标准定义了 memcpy7.21.2/1作为

For all functions in this subclause, each character shall be interpreted as if it had the type unsigned char (and therefore every possible object representation is valid and has a different value).

The memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined.

但是,如果存在使用 p之后,这可能会导致未定义的行为,具体取决于位模式。如果没有发生这样的使用,那么该代码在 C 中就可以了。


根据 C++ 标准,我认为在这个问题上还很不清楚,我认为以下内容成立。请不要将此解释视为唯一可能的解释 - 模糊/不完整的规范留下了很大的猜测空间。

(1)是有问题的,因为 &p 的对齐方式unsigned 可能不行类型。它改变了存储在 p 中的对象的类型。成为 unsigned int .只要您以后不通过 p 访问该对象, 别名规则没有被破坏,但对齐要求可能仍然存在。

(2)但是没有对齐问题,因此是有效的,只要您不访问 p之后作为 void* ,这可能会导致未定义的行为,具体取决于 void* type 解释存储的位模式。我不认为对象的类型因此而改变。

有一个很长的GCC Bugreport这还讨论了通过这种转换产生的指针写入的含义以及与placement-new的区别是什么(该列表上的人不同意它是什么)。

关于c++ - C 别名规则和 memcpy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3275353/

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