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

查看:120
本文介绍了ç别名规则和memcpy的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在回答另一个问题时,我认为下面的例子:

While answering another question, I thought of the following example:

void *p;
unsigned x = 17;

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

1号线断裂重叠规则。 2号线,但是,是OK WRT。别名规则。现在的问题是:为什么?该编译器对功能如memcpy的特殊的内置知识,还是有一些其他的规则,使得memcpy的好不好?有没有实施标准C的memcpy样的功能没有打破别名规则?

Line 1 breaks aliasing rules. Line 2, however, is OK wrt. aliasing rules. The question is: why? Does the compiler have special built-in knowledge about functions such as memcpy, or are there some other rules that make memcpy OK? Is there a way of implementing memcpy-like functions in standard C without breaking the aliasing rules?

推荐答案

C标准在相当清楚。有效类型由 P 命名的对象是无效* ,因为它有一个声明的类型,请参阅 6.5 / 6 。在C99混叠规则适用于读取的的写和写无效* 通过无符号左值在(1)是根据 6.5 / 7 未定义的行为。

The C Standard is quite clear on it. The effective type of the object named by p is void*, because it has a declared type, see 6.5/6. The aliasing rules in C99 apply to reads and writes, and the write to void* through an unsigned lvalue in (1) is undefined behavior according to 6.5/7.

在此相反,的memcpy (2)是好的,因为 unsigned char型* 可引用任何对象( 6.5 / 7 )。该标准定义了的memcpy 7.21.2 / 1

In contrast, the memcpy of (2) is fine, because unsigned char* can alias any object (6.5/7). The Standard defines memcpy at 7.21.2/1 as

有关在本节的所有功能,每个角色应是间preTED,如果它有unsigned char类型(因此每一个可能的对象,再presentation是有效的,具有不同的值)。

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).

memcpy函数拷贝n个字符从对象指向S2到对象由s1指向的。如果复制操作是重叠的对象之间,行为是理解过程网络斯内德。

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 的事后,这可能取决于位模式导致未定义的行为。如果这样的使用不会发生,即code是罚款C.

However if there exist a use of p afterwards, that might cause undefined behavior depending on the bitpattern. If such a use does not happen, that code is fine in C.

据在 C ++标准,这在我看来是很不明朗的问题,我认为下面成立。请不要把这个跨pretation作为唯一可能的 - 模糊的/不完整的规范留下了很大的炒作空间。

According to the C++ Standard, which in my opinion is far from clear on the issue, i think the following holds. Please don't take this interpretation as the only possible - the vague/incomplete specification leaves a lot of room for speculation.

(1)是有问题的,因为排列&安培; P 可能不是确定的无符号键入。它改变存储在 P unsigned int类型对象的类型。只要你不访问该对象稍后通过 P ,重叠规则未破,但对齐要求仍可能。

Line (1) is problematic because the alignment of &p might not be ok for the unsigned type. It changes the type of the object stored in p to be unsigned int. As long as you don't access that object later on through p, aliasing rules are not broken, but alignment requirements might still be.

(2)但是没有对齐的问题,因此是有效的,只要你不访问 P 在以后作为无效* ,这取决于如何使用无效* 类型间$ p这可能会导致不确定的行为$其中pts存储的位模式。我不认为这个对象的类型,从而改变了。

Line (2) however has no alignment problems, and is thus valid, as long as you don't access p afterwards as a void*, which might cause undefined behavior depending on how the void* type interprets the stored bitpattern. I don't think that the type of the object is changed thereby.

有很长的 GCC bug报告通过指针还讨论写入的影响起因于这样一个演员和什么区别来放置新的(人名单上不同意它是什么)。

There is a long GCC Bugreport that also discusses the implications of a write through a pointer that resulted from such a cast and what the difference to placement-new is (people on that list aren't agreeing what it is).

这篇关于ç别名规则和memcpy的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆