在玩了不同的数组类型后,我确定每个元素需要2位'填充'。例如,如果数组的数据类型是.int(32位或2 ^ 5),则总共有4个存储器位置(总共2 ^ 7位)专用于阵列的每个元素。另一个例子是如果数据类型是.short(16位或2 ^ 4),那么数组的每个元素都包含64位(2 ^ 6)
这是一个例子。
.data
IntArray:
.int 10, 20, 30, 40, 50
(gdb) info variables
0x080490a4 IntArray
(gdb) x/1wt 0x080490a4
0x80490a4 : 00000000000000000000000000001010
(gdb) x/1wt 0x080490a5
0x80490a5 : 00010100000000000000000000000000
(gdb) x/1wt 0x080490a6
0x80490a6 : 00000000000101000000000000000000
(gdb) x/1wt 0x080490a7
0x80490a7 : 00000000000000000001010000000000
(gdb) x/1wt 0x080490a8
0x80490a8 : 00000000000000000000000000010100
很明显,内存位置0x080490a4
包含数组的第一个元素(值10)。很明显,内存位置0x080490a8
包含数组的第二个元素。
我的问题涉及0x080490a5
,0x080490a6
,0x080490a7
的内容。这些内存位置有什么意义?我是否忽略了Arrays如何运作的一些细节?
答案 0 :(得分:0)
每个数组元素的大小 nothing 与数组中的元素数量有关。它仅由存储在数组中的数据类型决定。如果您有int[]
,则每个数组元素都与int
一样大。另一方面,int
的大小取决于操作系统和硬件平台ABI,在您可能遇到的大多数计算机系统上都是32位。
要计算每个数组的大小,必须将每个元素的大小乘以元素数。因此,对于int a[4]
:
size = sizeof(int) * 4 = 32 * 4 bits = 2 ^ 5 * 2 ^ 2 bits = 2 ^ 7 bits = 128 bits = 16 bytes
数组的大小,而不是每个单独元素的大小。
现在,x/1wt
GDB命令显示存储在提供的地址中的字的内容。只要地址指向数组元素,您应该看到它的内容。但是当你从一个元素转到下一个元素时,你需要在每个元素中添加字节数,而不是将位置移动一个字节。在你的情况下:
0x080490a4
是第一个数组元素的地址0x080490a8
是第二个数组元素的地址0x080490a5
,0x080490a6
和0x080490a7
都是非对齐的(即它们不是字长的倍数)地址,每个地址指向4个字节。在这4个字节中,有些属于第一个,有些属于第二个元素。由于x86 CPU为little-endian,其中最少有效字节(LSB)首先出现,因此这两个元素的物理内存布局为:
0x080490a4: 00001010 00000000 00000000 00000000
0x080490a8: 00010100 00000000 00000000 00000000
通过单个字节增加地址,您的计算机会看到:
0x080490a5: 00000000 00000000 00000000 00010100
0x080490a9: 00000000 00000000 00000000 ...
即。存储在0x080490a5
中的值有:
作为其三个最低有效字节,第一个数组元素的三个最重要的字节
作为第二个数组元素的第一个字节(即最不重要的一个)的最重要字节
由于x86是little-endian并且GDB重新排列它显示的字节,所以首先显示MSB,你得到:
0x80490a5: 00010100 00000000 00000000 00000000