c99中与类型无关的memcpy
与
Do any compilers transfer effective type through memcpy/memmove相关但有些不同
在C89中,memcpy和memmove的行为就像使用字符类型访问源和目标一样,将源的所有位复制到目标,而不考虑要复制的数据类型. C99更改语义,以便如果将具有有效类型的对象复制到没有声明类型的存储[通常是从malloc或其他此类函数接收的存储],则会在目标存储中创建一个只能使用源类型访问的对象. 例如,以下代码将在C89上具有完全定义的行为 #include <stdio.h> #include <string.h> void increment_32_bit_uint(void *p) { uint32_t temp; memcpy(&temp,p,sizeof temp); temp++; memcpy(p,&temp,sizeof temp); } int main(void) { unsigned *ip = malloc(sizeof (unsigned)); unsigned long *lp = malloc(sizeof (unsigned long)); *ip = 3; *lp = 6; increment_32_bit_uint(ip); increment_32_bit_uint(lp); printf("%u %lu",*ip,*lp); return 0; } 根据C99规则,将分配的存储传递给“increment_32_bit_uint”函数将使其将有效类型设置为uint32_t,即使所有三种类型具有相同的表示形式,它也不能与“unsigned”和“unsigned long”的类型相同.因此,编译器可以使用将该存储作为uint32_t以外的类型读取的代码执行任何喜欢的操作,即使该类型具有相同的表示形式. 在C99或C11中,有没有办法以允许编译器生成有效代码的方式执行复制,但会迫使编译器将目标视为包含没有有效类型的位模式[因此可以使用任何类型访问]? 解决方法
如果你只是为函数使用返回类型,你可以摆脱所有有效的类型问题.
uint32_t increment_32_bit_uint (const void* p) { u32_t result; memcpy(&result,sizeof(result)); result++; return result; } 这将迫使调用者小心他们的类型.当然,理论上这是某种不可变对象,而不是变量的就地变化.但是在实践中,如果你使用它,我认为无论如何你都会从中获得最有效的代码 x = increment_32_bit_uint(&x); 通常,我没有看到任何严格的别名优化如何在实际应用程序中有用,如果它们不将stdint.h类型视为与它们的原始数据类型等价的兼容类型.特别是,它必须将uint8_t视为字符类型,否则所有专业的低级C代码都会中断. 你的情况也一样.如果编译器知道unsigned int是32位,为什么它会决定为uint32_t的用户引起别名问题,反之亦然?这就是你如何使编译器变得无用. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |