C语言中结构体自赋值(指针解引用)是否为定义行为?
C语言结构体自赋值的合法性问题
问题描述
若两个指针指向同一个结构体变量,对其中一个解引用后赋值给另一个解引用的指针,该行为是否属于C标准定义的合法行为?
代码示例
struct Struct { int member; }; int main() { struct Struct s, *p1, *p2; s.member = 1234; p1 = p2 = &s; *p1 = *p2; // is this allowed? }
疑问背景
在Stack Overflow相关讨论中,有观点提到结构体赋值大致等效于memcpy,部分编译器甚至会将赋值语句编译为memcpy调用。但memcpy在内存区域重叠时行为未定义,因此疑惑结构体自赋值的行为是否符合标准定义。此外,是否需要添加判断语句if (p1 != p2) *p1 = *p2;或改用memmove?
补充场景
该问题源于在C语言中实现slot map时,删除元素会将数组末尾元素复制到删除位置,当删除的是末尾元素时会出现自赋值情况。
解答
- 结构体自赋值是C标准明确允许的合法行为,不存在未定义行为。
- 虽然部分编译器会用
memcpy实现结构体赋值,但C标准要求编译器必须保证自赋值场景的安全性:当检测到赋值操作的左右操作数指向同一对象时,编译器不能直接使用存在未定义行为的memcpy,而是会采用安全的实现方式(比如等价于memmove的逻辑,或者逐个成员复制)。 - 不需要额外添加
if (p1 != p2)判断,也不需要改用memmove。直接编写*p1 = *p2即可,无论两个指针是否指向同一对象,标准都保证行为是定义良好的。 - 针对slot map的场景:删除末尾元素时的自赋值完全安全,无需额外处理,直接执行赋值语句即可。
内容的提问来源于stack exchange,提问作者Michael Jones
相关产品推荐
相关产品推荐

