【发布时间】:2014-02-08 15:02:30
【问题描述】:
在学习 c 的过程中,我实现了自己的 memcpy 函数。我在函数中使用了更广泛的类型(uint32_t)。 (为简单起见,该函数仅限于 4 的倍数且数据正确对齐的类型)
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];
}
我对类型双关语和严格别名做了一些阅读,我相信上面的函数违反了规则。正确的实现是这样的,因为您可以使用字符:
void memcpy4( void* dst , void* src , int size )
{
for ( int i = 0 ; i < size ; i++ )
((char *)dst)[i] = ((char *)src)[i];
}
我尝试通过联合进行一些强制转换,但结果也无效。
怎样才能用更宽的类型来实现这样的功能而不违反严格的别名规则?
【问题讨论】:
-
由于这是一个学习练习,让我建议您学习另一件事:永远不要使用有符号整数作为大小和索引。使用无符号整数,或更好的
std::size_t。这种memcpy()的实现是基于signed int 攻击的经典示例。 -
您的实现使用
uint32_t。uint32_t有多大?我不知道 - 我知道我可能会猜到它会是什么,但我不知道 - 我绝对不知道在任何和所有平台上。试试size /= sizeof(uint32_t)。 -
一个正确的实现必须处理这样一个事实,即有问题的指针(源和目标)可能相对于对特定架构可能重要的任何边界都未对齐。我知道这只是一个练习,但我鼓励你坐下来处理所有的边缘条件。这就是学习的方式。
-
sizeof(uint32_t)通常为 4,但在CHAR_BIT > 8的某些平台上可能小于此值。 -
@self.:
uint32_t被定义为 32 位,而不是 4 字节。字节不要求为 8 位,而且有很多平台不是。
标签: c++ c memcpy strict-aliasing