通过的memcpy / memmove与做任何的编译器传递有效的类型 [英] Do any compilers transfer effective type through memcpy/memmove

查看:123
本文介绍了通过的memcpy / memmove与做任何的编译器传递有效的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据N1570 6.5 / 6:

According to N1570 6.5/6:

如果一个值被复制到一个对象具有使用的memcpy或的memmove没有声明的类型,或者被复制为字符类型的阵列,则有效类型
  对于访问和不修改的值的后续访问修改的对象是从哪个值将被复制的有效对象的类型,如果它有一个。

If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one.

这将表明,即使在一个系统中长和其他一些整数类型具有相同的重presentation,下面将调用未定义行为:

That would suggest that even on a system where "long" and some other integer type have the same representation, the following would invoke Undefined Behavior:

#if ~0UL == ~0U
  #define long_equiv int
#elif ~0UL == ~0ULL
  #define long_equiv long long
#else
#error Oops
#endif
long blah(void)
{
  long l;
  long_equiv l2;
  long_equiv *p = malloc(sizeof (long));
  l = 1234;
  memcpy(p, &l, sizeof (long));
  l2 = *p;
  free(p); // Added to address complaint about leak
  return l2;
}

由于数据通过显然具有有效的类型指出,和对象通过指向 p 并没有声明的类型,在的memcpy 应设置有效的类型存储到。由于阅读类型的左值使用 long_equiv 读有效键入是不允许的,在$的对象C $ç将调用未定义的行为。

since the data pointed to by l clearly has effective type long and the object pointed to by p has no declared type, the memcpy should set the effective type of the storage to long. Since reading use of an lvalue of type long_equiv to read an object with effective type of long is not allowed, the code would invoke Undefined Behavior.

由于之前C99 的memcpy 是标准的方式,一种类型的数据复制到另一种类型的存储之一,约新规则的memcpy 的原因有很多现有的code的调用未定义的行为。如果规则已经代替了,使用的memcpy 写分配存储没有留下任何有效类型的目的地,则该行为将被定义。

Given that prior to C99 memcpy was one of the standard ways to copy data of one type to storage of another type, the new rules about memcpy cause a lot of existing code to invoke Undefined Behavior. If the rule had instead been that using memcpy to write to allocated storage leaves the destination without any effective type, the behavior would be defined.

有没有不表现得好像的memcpy 用于信息复制到分配的存储时留下的有效类型目标未设置的,还是应该使用<$的任何编译器C $ C>的memcpy 数据转换的目的被认为是安全?如果一些编译器做有效申请类型源到目的地,会是什么类型无关的方式复制数据的正确方法?什么是复制为字符类型的数组?

Are there any compilers which do not behave as though memcpy leaves the effective type of the destination unset when used to copy information to allocated storage, or should use of memcpy for purposes of data translation be considered "safe"? If some compilers do apply effective type of the source to the destination, what would be the proper way of copying data in type-agnostic fashion? What is meant by "copied as an array of character type"?

推荐答案

C标准说,有效的类型转移。因此,根据定义,所有符合的编译器传送的有效类型。

The C standard says that the effective type is transferred. Therefore, by definition, all conforming compilers transfer the effective type.

您code样品导致不确定的行为由于违反了严格别名规则,因为有效的类型的值是由类型的左值读长长

Your code sample causes undefined behaviour by violating the strict aliasing rule, because a value of effective type long is read by an lvalue of type long long.

这也是如此在C89,我不知道你指的关于在C99新规什么(除了一个事实,即长长不在C89)。

This was also true in C89, I'm not sure what you refer to about "new rules in C99" (other than the fact that long long was not in C89).

这是事实,当C是标准化的,一些现有的code的未定义行为。而且这也是事实,人们继续写code。与未定义的行为。

It is true that when C was standardized, some existing code had undefined behaviour. And it is also true that people continue to write code with undefined behaviour.

什么是复制为字符类型的数组?

What is meant by "copied as an array of character type"?

这使用字符类型意味着复制字符逐个字符。

This means copying character-by-character using a character type.

什么是类型无关的方式复制数据的正确方法?

what would be the proper way of copying data in type-agnostic fashion?

这是不可能的擦除有效型,所以据我所知。要使用正确读取值久长* ,您必须指向有效类型的位置长长

It's not possible to "erase effective type", so far as I know. To correctly read a value using a long long *, you must be pointing to a location of effective type long long.

在您的code,例如:

In your code, for example:

// If we have confirmed that long and long long have the same size and representation
long long x;
memcpy(&x, p, sizeof x);
return x;

联盟走样是另一种选择。

Union aliasing is another option.

如果你不喜欢这一切,然后用编译 -fno严格走样

If you don't like all this then compile with -fno-strict-aliasing.

这篇关于通过的memcpy / memmove与做任何的编译器传递有效的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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