然后在C中取消引用指针
在C中使用char
缓冲区时,有时一次处理int
数据块会更有用,也更有效。 为此,我可以将我的char *
转换为int *
并使用该指针代替。 但是,我并不完全相信这种方式与我认为的方式相同。
例如,假设我有char *data
, *(int32_t *)data = -1
总是覆盖字节data[0]
, data[1]
, data[2]
和data[3]
而没有其他字节?
扩展我的评论。
这里有两个主要问题:
- 它违反了严格别名 。
- 你可能会破坏对齐。
违反严格别名是技术上未定义的行为 。 您可以使用char*
为任何数据类型设置别名,但不能反过来。
您可以在GCC上解决f[no-]strict-aliasing
问题。
另一个问题是对齐。 char
指针可能未正确对齐。 如果硬件不支持未对齐访问,则访问未对齐的数据可能会导致性能下降甚至硬件exception。
如果性能不是问题,那么完全certificate的方法是将memcpy()
传递给int
数组缓冲区。
解决了这两个问题后,您的示例包括:
*(int32_t *)data = -1
如果sizeof(int32_t) == 4
,则覆盖data[0]
, data[1]
, data[2]
和data[3]
应该按预期工作。 只要注意字节顺序……
这是技术上未定义的行为,标准对这样的别名指针的结果保持沉默。 标准学者会说,以这种方式调用未定义的行为可能导致从损坏的数据到系统崩溃到Ragnarok的任何事情。
实际上,这取决于您的硬件。 大多数现代系统(例如x86,x64,PPC,MIPS,ARM)以您描述的方式处理字大小的写入,除了写入未对齐的地址将导致崩溃。 此外,这是endianness发挥作用; 在一个小端系统上
char foo[4]; *((uint_32*)(foo)) = 0x01020304; // the following are now true: foo[0] == 0x04; foo[1] == 0x03; foo[2] == 0x02; foo[3] == 0x01;
简短的回答是,除非您确切知道程序运行的硬件,否则这是不安全的。
如果您确实控制了编译的硬件,那么您可以预测编译器将执行的操作; 我已经使用这个技巧来加速嵌入式系统上字节数组的打包。
不,不一定。 如果数据未正确对齐,则可能根本不起作用。 假设它正确对齐,它可能会覆盖下一个sizeof(int)
字节,而不是其他任何东西,但我不确定即使那么多也完全可以保证。