Memcpy实现,严格别名 [英] Memcpy implementation, strict aliasing

查看:131
本文介绍了Memcpy实现,严格别名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

学习c时,我实现了自己的memcpy函数。我在函数中使用了一个更宽的类型( uint32_t )。 (为简单起见,函数仅限于4的倍数类型,并且数据正确对齐)

  void memcpy4 dst,void * src,int size)
{
size / = 4;

for(int i = 0; i ((uint32_t *)dst)[i] =((uint32_t *)src)[i]
}

我在类型打印和严格的别名上做了一些阅读,打破规则。正确的实现是这样的,因为你可以使用一个字符:

  void memcpy4(void * dst,void * src,int size )
{
for(int i = 0; i ((char *)dst)[i] =((char *)src)[i]
}

我试图通过联合做一些转换,但结果是



如何用更宽的类型实现此类函数,而不破坏严格别名规则?

$ b
$ b

标准C不支持使用除字符类型之外的 memcpy



Quality C实现提供了一个优化的 memcpy 实现,它使用多个单字节副本执行高效复制,但是它们使用特定于实现的代码来实现。他们可以通过使用 -fnostrict-aliasing 开关编译 memcpy 实现来告诉编译器别名规则将违反代码,通过依赖于特定的C实现的已知功能,以确保代码将工作(如果你编写的编译器,你可以设计它,使您的实现 memcpy memcpy



此外,C实现可以优化 memcpy 调用,它们出现在源代码中,通过直接指令替换它们来执行操作或通过简单地更改程序的内部语义。 (例如,如果将 a 复制到 b 中,编译器可能根本不执行复制, a 其后的代码访问 b 。)



在违反混叠规则的情况下实现自己的特殊复制操作,如果使用GCC或Clang,则使用 -fnostrict-aliasing 编译。如果使用另一个编译器,请检查其文档中的选项以禁用别名规则。 (注意:我使用的Apple的GCC默认禁用严格别名,并接受 -fstrict-aliasing ,但不是 -fnostrict-aliasing 。我假设非Apple GCC接受 -fnostrict-aliasing 。)



一个好的C实现,你可能会发现你的 memcpy4 的四字节拷贝实现的性能不如原生 memcpy ,具体取决于具体情况。


While learning c I have implemented my own memcpy functions. I have used a wider type( uint32_t) in the function. (For simplicity the function is restricted to types that are multiples of 4 and the data is properly aligned )

void memcpy4( void* dst , void* src , int size )
{
    size /= 4;

    for ( int i = 0 ; i < size ; i++ )
        ((uint32_t*)dst)[i] = ((uint32_t*)src)[i];
}

I did some reading on type punning and strict aliasing and I believe the function above breaks the rule. The correct implementation would be this since you can use a char:

void memcpy4( void* dst , void* src , int size )
{
    for ( int i = 0 ; i < size ; i++ )
        ((char *)dst)[i] = ((char *)src)[i];
}

I tried to do some casting trough an union, but that turned out to be invalid as well.

How could such function be implemented with a wider type and not break the strict aliasing rule?

解决方案

The way to implement memcpy using more than single-byte copies is to use non-standard C.

Standard C does not support implementing memcpy using other than character types.

Quality C implementations provide an optimized memcpy implementation that performs efficient copying using more than single-byte copies, but they use implementation-specific code to do so. They may do this by compiling the memcpy implementation with a switch such as -fnostrict-aliasing to tell the compiler the aliasing rules will be violated in the code, by relying on known features of the specific C implementation to ensure the code will work (if you write the compiler, you can design it so that your implementation of memcpy works), or by writing memcpy in assembly language.

Additionally, C implementations may optimize memcpy calls where they appear in source code, replacing them by direct instructions to perform the operation or by simply changing the internal semantics of the program. (E.g., if you copy a into b, the compiler might not perform a copy at all but might simply load from a where subsequent code accesses b.)

To implement your own specialized copy operation while violating aliasing rules, compile it with -fnostrict-aliasing, if you are using GCC or Clang. If you are using another compiler, check its documentation for an option to disable the aliasing rules. (Note: Apple’s GCC, which I use, disables strict aliasing by default and accepts -fstrict-aliasing but not -fnostrict-aliasing. I am presuming non-Apple GCC accepts -fnostrict-aliasing.)

If you are using a good C implementation, you may find that your four-byte-copy implementation of memcpy4 does not perform as well as the native memcpy, depending on circumstances.

这篇关于Memcpy实现,严格别名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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