reinterpret_cast <t> </t>的反直觉效果

时间:2014-06-02 19:36:52

标签: c++ reinterpret-cast

我有以下代码:

std::vector<short> vec{ 0, 2, 0, 4 };
int* lpvec = reinterpret_cast<int*>(&vec[0]);

(在VC12下编译:短2个字节,int 4个字节) 我认为它会产生:

lpvec[0] = 2, 
lpvec[1] = 4

但令我惊讶的是输出

lpvec[0] = 2 * 2^16 + 0 = 131072, 
lpvec[1] = 4 * 2^16 + 0 = 262144

我说反直觉,因为我认为短片的矢量以下列模式排列在记忆中:

+---------+---------+---------+---------+
| 2 bytes | 2 bytes | 2 bytes | 2 bytes |
+---------+---------+---------+---------+
|       0 |       2 |       0 |       4 |
+---------+---------+---------+---------+

所以, int 看起来会一样,但占用的空间是原来的两倍:

+-------------+------------+
|   4 bytes   |  4 bytes   |
+-------------+------------+
| 0*2^16 + 2  | 0*2^16 + 4 |
+-------------+------------+

有人会告诉我为什么我错了吗?

1 个答案:

答案 0 :(得分:8)

哦,不,这不酷......

您正在做的是调用未定义的行为

short*投射到int*会违反别名规则,但主要是“意外”结果是由于实现定义了endianness的整数值。


Little-vs Big-endian

“Endianness”是存储在整数类型中的字节(表示值)的顺序,在本例中为int

您的平台似乎正在使用 little-endian ;意味着首先存储最低有效字节,而您的预期结果取决于使用 big-endian 的实现;如上所述,情况并非如此。


您的实施将short { 2 }存储为[0x02][0x00],这会使int指向的lpvec等同于[0x00][0x00][0x02][0x00]

所涉及的计算,因为您的平台使用 big-endian 将是:

(2^0 * 0) + (2^8 * 0) + (2^16 * 2) + (2^24 * 0) = 131072

注意:上面假设一个字节宽8位,这也是实现定义的。