在64位系统中复制unsigned int 2次和unsigned long 1次有什么区别?

YOU*_*YOU 0 c linux 64-bit gcc

有什么区别

*(unsigned*)d = *(unsigned*)s; 
d+=4; s+=4; 
*(unsigned*)d = *(unsigned*)s; 
d+=4; s+=4;
Run Code Online (Sandbox Code Playgroud)

*(unsigned long*)d = *(unsigned long*)s;
d+=8; s+=8;
Run Code Online (Sandbox Code Playgroud)

在64位系统?

Ste*_*sop 5

假设在填充位或严格别名规则方面没有任何不愉快的事情发生,并且假设类型的大小与您期望的一样,并且假设存储区域不重叠并且正确对齐,那么它们每个都复制8个字节.一个地方到另一个.

当然,除了实际效果之外,性能和/或代码大小可能存在差异.

如果你看到了什么破坏,那么看看发出的实际代码,可能会告诉你出了什么问题.除非您已经开启了很多优化,甚至可能进行了优化,否则我不会立即明白为什么那些与AMD64,Ubuntu和gcc不相同.

我提到过的事情可能会出错:

  • 填充位 - 不适用于GCC,但标准允许unsigned使用unsigned long填充位,如果是,则可能存在位模式,这些位模式是一个或两个的陷阱表示,一旦取消引用就会爆炸.
  • 严格别名 - 不太可能影响该代码的作用,但可能会影响用于检查结果的代码.例如,如果s并且d是将指针转换为double的结果uint8_t*,并且您查看生成的double,那么在一种或两种情况下,您可能看不到更改的效果,因为您有非法的类型双关语.
  • 类型的大小 - 不应该在这里适用,因为64位linux是LP64,但显然如果sizeof(long) == 4那么两者不相等.long在64位Windows系统上是32位,而不是64位Linux系统.
  • 重叠 - 如果d == s + 4,则两个代码片段具有不同的效果.因此,除非编译器知道ds指向完全不同的位置(这就是C99 restrict的用途),否则你不会看到第一个被优化成为第二个.
  • alignment - 我不记得对于x86-64的对齐要求是什么:对于x86,你可以通过一个未对齐的读/写来逃避它,它只是更慢.一般来说,如果sd正确对齐int但不是long那么就会有差异.(编辑:显然,您可以在x86-64上启用或禁用未对齐访问的硬件异常).