我有以下代码:
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 |
+-------------+------------+
有人会告诉我为什么我错了吗?
答案 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
位,这也是实现定义的。