c别名规则和memcpy[英] C aliasing rules and memcpy

本文是小编为大家收集整理的关于c别名规则和memcpy的处理方法,想解了c别名规则和memcpy的问题怎么解决?c别名规则和memcpy问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

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

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中的混叠规则适用于读取和的写入,并且根据(1)中的unsigned lvalue写入void*是根据6.5/7的不确定行为.

相反,(2)的memcpy是可以的,因为unsigned char*可以别名任何对象(6.5/7).标准定义memcpy at 7.21.2/1为

对于本款中的所有函数,每个字符应被解释为具有unsigned char的类型(因此,每个可能的对象表示都是有效的,并且具有不同的值).

memcpy函数将n个字符从s2指向的对象复制到s1指向的对象.如果在重叠的对象之间进行复制,则该行为是未确定的.

然而,如果之后存在p,则可能会导致不确定的行为,具体取决于bitpattern.如果没有发生这样的用法,则该代码在C中很好.


根据 c ++标准,我认为这在这个问题上远不清楚,我认为以下内容存在.请不要将这种解释视为唯一的可能 - 模糊/不完整的规范为猜测留出了很多空间.

行(1)是有问题的,因为&p的对齐方式可能不正确.它将存储在p中的对象的类型更改为unsigned int.只要您以后不访问该对象,通过p,混杂规则不会破坏,但是对齐要求仍然可能存在.

line (2)但是没有对齐问题,因此只要您不访问p之后是void*,这可能会导致不确定的行为,这取决于void* void*的方式解释如何解释存储的BitPattern.我认为对象的类型不会因此而更改.

有一个长 gcc bugreport 通过这样的演员产生的指针写作以及与安置新的区别是什么(该列表上的人并不同意它是什么).

本文地址:https://www.itbaoku.cn/post/359183.html