这个就有意思了, 我们发现, 我们如果换一种书写方式, 可以更直观理解数组在内存中模样.
事件起因
前些天阅读一本js 相关书籍的时候, 看到这么一段话.
var buffer = new ArrayBuffer(12);var x1 = new Int32Array(buffer);x1[0] = 1;var x2 = new UInt8Array(buffer);x2[0] = 2;x1[0] // 2
显而易见, 上述寥寥代码的主要内容是在阐述 TypedArray仅仅作为 ArrayBuffer 视图读写内存的道理. x1和x2公用了同一段内存._
而我今天想说这里有一个很有意思的事情.
字节序
大家公认的概念, 也是计算机基础理论知识的一部分.
内存中使用8个二进制位(bit)表示一个字节(Byte).
UInt8 是使用一个字节表示的无符号整数
UInt32 则是使用了4个字节表示的无符号整数
我们使用无符号整数这样简单的数据结构, 来看看刚刚的赋值过程做了什么.
x1[0] = 1
我们知道, x1是一个 Int32视图, 所以第一个元素的长度是四个字节. 也就是说, 该部分的值是 0x000001
.
高位 | 低位 | ||
---|---|---|---|
00 | 00 | 00 | 01 |
x2[0] = 2
我们知道, x2是一个 Int8视图, 所有第一个元素的长度是一个字节, 也就是说, 该部分的值是 0x02
.
瞧, 现在 x1[0] 应该变成什么样?
是 0x00000002
?
高位 | 低位 | ||
---|---|---|---|
00 | 00 | 00 | 02 |
还是 0x02000001
?
高位 | 低位 | ||
---|---|---|---|
02 | 00 | 00 | 01 |
这个问题的本质, 即 __内存中, Int32数据类型内部的四个字节, 是低位在前, 还是高位在前?__.
如果是高位在前, 则x2[0]指向的是 x1[0]最高位的字节. 反之, 则是指向的最低位.
关于字节序, 在计算机的世界里有这样一种定义和区分. 大端序
/小端序
.
详细设定我们参考 (wiki)[ 就好.
我们绝大多数时候再现代计算机上使用的字节, 都是小端序.
而网络传输中使用的是大端序, 如 IP 报头
瞧, 书写一个数组试试.
假设我们有一个 UInt16Array(3)
var x3 = new UInt16Array([11, 22, 33]);
我们在草稿纸上会这么写
x3[0] | x3[1] | x3[2] |
---|---|---|
11 | 22 | 33 |
也就是说我们习惯性把第一元素写在左边. 换成十六进制的写法就是
如果现在没看出来为什么我想说从左到右书写数组会造成有趣的误解, 那我再试着用二进制方式把这个数组写出来 :)
注意,最左边一个格子是 x3[0] 哦! 这时候, 我们试着使用x2这样的 UInt8Array 视图来解读这个数组.
正确的解读应该是
00001011 | 00000000 | 00010000 | 00000000 | 00100001 | 00000000 |
---|---|---|---|---|---|
0x0B | 0x00 | 0x16 | 0x00 | 0x21 | 0x00 |
11 | 0 | 22 | 0 | 33 | 0 |
而不是
00000000 | 00001011 | 00000000 | 00010000 | 00000000 | 00100001 |
---|---|---|---|---|---|
0x00 | 0x0B | 0x00 | 0x16 | 0x00 | 0x21 |
0 | 11 | 0 | 22 | 0 | 33 |
因为, 小端字节序的设计中, __低位在前__.
所以, 如果我们一开始就在脑海中将所构思的数组从右往左书写
x3[2] | x3[1] | x3[0] |
---|---|---|
33 | 22 | 11 |
0x0021 | 0x0016 | 0x000B |
00000000 00100001 | 00000000 00010000 | 00000000 00001011 |
改变数据类型去解读的结果则是
x2[5] | x2[4] | x2[3] | x2[2] | x2[1] | x2[0] |
---|---|---|---|---|---|
00000000 | 00100001 | 00000000 | 00010000 | 00000000 | 00001011 |
0x00 | 0x21 | 0x00 | 0x16 | 0x00 | 0x0B |
0 | 33 | 0 | 22 | 0 | 11 |
看! 完全不会有交换字节带来的误解!