严格的混叠规则和std::copy

Strict aliasing rules and std::copy

本文关键字:std 规则 copy      更新时间:2023-10-16

我有一个包含"序列化"数据的字符数组,我需要将其解释为'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也有同样的问题,这是"允许的"。

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

EDIT:我应该补充一下,我很欣赏关于如何最好地做到这一点的答案,它们很有趣,但我的问题更多的是关于这是合法的而不是我如何做到这一点。

这相当于std::memcpy(&i, data, sizeof(int)),并且存在依赖于端序和假设sizeof(int) <= sizeof(data)的相同问题,这与平台相关。char *不受严格混叠规则约束

为什么不直接写:

#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

然后,例如要获得{4, 5, 6, 7}部分的int,您可以这样写:

i = TO_INT(data+4);

注意:这不是用于复制粘贴的代码,它给出了一个想法。如果你有不同的系统,int的大小不同,或者除了char *之外,你可能会给宏其他类型的指针,你自己做错误检查。

满足您的需求吗?

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

gcc 4.5.2编译时没有任何警告,即使打开了-O3 -Wall