严格的别名规则和std :: copy

时间:2011-09-05 09:03:54

标签: c++

我有一个包含“序列化”数据的字符数组,我需要将其解释为'int'。先前我只是将一个指向该位置的指针转换为'int *'并取消引用以获取int数据,但是虽然它对我来说效果很好但它违反了严格的别名规则,因此未定义行为。

所以现在我使用memcpy将字节复制到int中,我认为这不是未定义的行为。但是我可以使用“std :: copy”吗?

例如

char data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int i;

std::copy(data, data+sizeof(int), reinterpret_cast<char*>(&i));

这本身并没有打破严格的别名规则,但任何可能的实现都会这样做......但是memcpy也有同样的问题并且是“允许的”。

这是标准的编译代码还是我需要坚持使用memcpy?

编辑:我应该补充一点,我指出了如何最好地做到这一点的答案,它们很有趣,但我的问题更多的是关于这是合法的而不是如何能够我这样做。

3 个答案:

答案 0 :(得分:4)

这等同于std::memcpy(&i, data, sizeof(int)),并且遇到依赖于字节序的相同问题以及sizeof(int) <= sizeof(data)的假设,它们是平台相关的。 char *免于严格别名规则。

答案 1 :(得分:0)

为什么不写:

#if __YOU_DEFINE_IF_LITTLE_ENDIAN__
#define TO_INT(d) ((((int)(d)[0]))|
                  (((int)(d)[1])<<8)|
                  (((int)(d)[2])<<16)|
                  (((int)(d)[3])<<24))
#else
#define TO_INT(d) ((((int)(d)[3]))|
                  (((int)(d)[2])<<8)|
                  (((int)(d)[1])<<16)|
                  (((int)(d)[0])<<24))
#endif

然后,例如,为了获得代码的int部分的{4, 5, 6, 7},您可以写下:

i = TO_INT(data+4);

注意:这不是复制粘贴的代码,它提供了一个想法。如果您有int不同大小的不同系统,或者可以在char *旁边为宏提供其他类型的指针,请执行自己的错误检查。

答案 2 :(得分:-1)

这是否符合您的需求?

int f (const char* x, size_t index)
  {
  const int* p = (const int*)x ;
  return p[index] ;
  }

gcc 4.5.2在没有任何警告的情况下编译它,即使-O3 -Wall已开启。