如何在不破坏严格别名规则的情况下有效地从char缓冲区复制小数据?

时间:2015-08-13 10:45:30

标签: c strict-aliasing

另一个问题的答案:Strict aliasing rule and 'char *' pointers表示使用Activity检查char*对象的二进制内容是可以的。但是使用T覆盖char缓冲区是不行的。

现在我有一个带有二进制数据的char缓冲区的函数。在阅读时会做这样的事情:

T*

如果我通过这样做打破严格的混叠,还有哪些更有效的方法?编译器在用少量字节调用时是否会优化memcpy调用?

2 个答案:

答案 0 :(得分:2)

  

如果我通过这样做打破严格的别名......

是的,你做了

  

还有哪些更有效的方法?

如果缓冲区必须为char,则需要在memcpy之前使用uint32_t才能访问该值。当然,如果你的所有值都是uint32_t s,你可以创建uint32_t s的缓冲区,并将其传递给用char s填充它的函数,因为严格别名是一个允许使用uint32_t*作为char*

  

编译器在用少量字节调用时是否会优化memcpy调用?

许多CPU都有memcpy的内置指令。现代编译器使用这些指令以提高效率。

答案 1 :(得分:1)

  

编译器在用少量字节调用时是否会优化memcpy调用?

对于此示例代码:

#define _CRT_SECURE_NO_WARNINGS // To allow usage of scanf in vc++2015
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main()
{
    // printf and scanf to prevent code elimination
    char bytes[ 4 ];
    scanf( "%s", bytes ); 
    char buffer[ 4 ];
    memcpy( buffer, bytes, 4 );
    printf( "%s", buffer );

    return 0;
}

Visual C ++ 2015生成了此程序集输出(发布版本,x64):

; memcpy was replaced by a simple register move
mov    eax, DWORD PTR bytes$[rsp] 
lea    rdx, QWORD PTR buffer$[rsp]                   ; setting arguments 
lea    rcx, OFFSET FLAT:??_C@_02DKCKIIND@?$CFs?$AA@ ; for printf call
; at this point copied array was actually stored in memory
mov    DWORD PTR buffer$[rsp], eax     
call   printf

所以,是的,现代编译器甚至不会调用该程序。