读取void *作为int指向char的安全性如何?
示例:测试系统中char的第一位,其中8位字符的访问速度比32位整数慢得多。
char c = 'B'; // a char here to illustrate the potentially dangerous case, but the
// point is this could be a char, could be an int... I am just
// interested in the first bit
void *v = &c;
int i = *(int *)v;
if (i & 0x01)
{
printf("yep");
}
似乎工作,但如果我的char(c)正好位于分配给此进程的有效内存的边缘,它是否会读入无效内存?或者系统是否足够聪明,可以在前8位后停止复制?
感谢
答案 0 :(得分:3)
在所有情况下都是未定义的行为。
在大多数实际系统中,如果c
靠近内存页面的末尾并且邻近,它将从c
和相邻内存正常读取,失败(具有访问冲突,即分段错误)页面标记为不可读。
在较小但仍然非常重要的系统中,您可能会遇到对齐错误和/或读取与c
重叠但在某个位置与c
重叠的32位值除了开始。
但是如果编译器抓住你这样做,它就会获得标准的许可,以非常破碎的方式“优化”你的所有代码。
如果您害怕8位访问速度较慢的系统,请使用int_fast8_t
代替char
。这可以让您的构建环境选择更好的可变大小。
答案 1 :(得分:2)
不,这不安全。
你的用例完全是假的,因为我从未听说过一个读取32位值比读取8位值更快的系统。如果有的话,它有时会反过来。
(即使你找到了这样一个系统,也要把这样的“优化”留给编译器。它会做得更好。)
答案 2 :(得分:1)
系统不够聪明,而且您的程序容易出现内存访问违规行为
答案 3 :(得分:1)
这只是未定义的行为。
另一方面,我可以想象一下这种情况会有效。请注意,在声明c
后,您声明v
。由于c
在堆栈上,通过将其地址强制转换为void*
然后取消引用它,您可能得到int
,它将来自c
的1个字节和来自{的3个字节{1}}。但这只是众多可能实现中的一种。
答案 4 :(得分:1)
int变量将加载3个字节加上您要加载的字节。你的演员也可能导致错位。并且,根据你在if中掩盖的方式,这个演员在不同于endianess的平台之间是不可移植的。这是一种糟糕的方法,重新构建您的系统以避免当前的情况。