Ole*_*eev 8 c c++ strict-aliasing memcpy
在询问"如何实现符合严格别名规则的memcpy函数"时,一般的答案就是这样的
void *memcpy(void *dest, const void *src, size_t n)
{
for (size_t i = 0; i < n; i++)
((char*)dest)[i] = ((const char*)src)[i];
return dest;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我理解正确的话,编译器可以自由地重新排序对memcpy的调用并访问dest,因为它可以使用任何其他指针类型的读取重新排序写入char*(严格的别名规则阻止仅对char*的读取进行重新排序)到任何其他指针类型).
这是正确的,如果是的话,有没有办法正确实现memcpy,还是我们应该依赖内置的memcpy?
请注意,这个问题不仅涉及memcpy,还涉及任何反序列化/解码功能.
严格别名规则明确地将强制char类型转换为类型(请参阅下面的最后一个要点),因此编译器将在您的情况下执行正确的操作.转换之类的东西时类型双关只是一个问题int来short.在这里,编译器可能会做出会导致未定义行为的假设.
C99§6.5/ 7:
对象的存储值只能由具有以下类型之一的左值表达式访问:
- 与对象的有效类型兼容的类型,
- 与对象的有效类型兼容的类型的限定版本,
- 与对象的有效类型对应的有符号或无符号类型的类型,
- 与有效类型的对象的限定版本对应的有符号或无符号类型的类型,
- 聚合或联合类型,包括其成员中的上述类型之一(包括递归地,子聚合或包含联合的成员),或者
- 一个字符类型.
由于(char*)dest和 都(char const*)src指向char,编译器必须假设它们可能是别名。另外,有一条规则说指向字符类型的指针可以为任何东西起别名。
所有这些都与 无关memcpy,因为实际签名是:
void* memcpy( void* restrict dest, void* restrict src, size_t n );
Run Code Online (Sandbox Code Playgroud)
这告诉编译器不能有别名,因为用户保证它。您不能使用memcpy复制重叠区域而不会导致未定义的行为。
无论如何,给定的实现没有问题。
| 归档时间: |
|
| 查看次数: |
1387 次 |
| 最近记录: |