读取void *作为int指向char的安全性如何?

时间:2014-01-18 22:17:32

标签: c++ c pointers memory void

读取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位后停止复制?

感谢

5 个答案:

答案 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的平台之间是不可移植的。这是一种糟糕的方法,重新构建您的系统以避免当前的情况。