版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1344505
在探究过数组和结构体这两种非原生的数据类型之后,可能会想知道这两种类型结合成结构体数组,会有什么特征。
先看一个例子:
#include <stdlib.h>
struct xuzhina_dump_c05_s3_3
{
short idx;
int sq;
};
void init( struct xuzhina_dump_c05_s3_3* test, int n )
{
for ( int i = 0; i < n; i++ )
{
test[i].idx = i;
test[i].sq = i*i;
}
}
int sum( struct xuzhina_dump_c05_s3_3* test, int n )
{
int sum = 0;
for ( int i = 0; i < n; i++ )
{
sum += test[i].sq;
}
return sum;
}
int main(int argc, char* argv[] )
{
if ( argc < 2 )
{
return 1;
}
int num = atoi( argv[1] );
struct xuzhina_dump_c05_s3_3* test =
(struct xuzhina_dump_c05_s3_3*)malloc( num * sizeof( struct xuzhina_dump_c05_s3_3 ) );
init( test, num );
return sum( test, num );
}
汇编(只看init和sum即可)
(gdb) disassemble init
Dump of assembler code for function _Z4initP21xuzhina_dump_c05_s3_3i:
0x080484d0 <+0>: push %ebp
0x080484d1 <+1>: mov %esp,%ebp
0x080484d3 <+3>: sub $0x10,%esp
0x080484d6 <+6>: movl $0x0,-0x4(%ebp) ;i
0x080484dd <+13>: jmp 0x8048511 <_Z4initP21xuzhina_dump_c05_s3_3i+65>
0x080484df <+15>: mov -0x4(%ebp),%eax
0x080484e2 <+18>: lea 0x0(,%eax,8),%edx ;edx = i*8
0x080484e9 <+25>: mov 0x8(%ebp),%eax ;eax = test
0x080484ec <+28>: add %eax,%edx ;edx = test[i]
0x080484ee <+30>: mov -0x4(%ebp),%eax ;i
0x080484f1 <+33>: mov %ax,(%edx) ;test[i].idx = i
0x080484f4 <+36>: mov -0x4(%ebp),%eax ;i
0x080484f7 <+39>: lea 0x0(,%eax,8),%edx ;edx = i*8
0x080484fe <+46>: mov 0x8(%ebp),%eax ;eax = test
0x08048501 <+49>: add %eax,%edx ;edx = test[i]
0x08048503 <+51>: mov -0x4(%ebp),%eax ;eax = i
0x08048506 <+54>: imul -0x4(%ebp),%eax ;eax *= i
0x0804850a <+58>: mov %eax,0x4(%edx) ;test[i].sq = eax
0x0804850d <+61>: addl $0x1,-0x4(%ebp) ;i++
0x08048511 <+65>: mov -0x4(%ebp),%eax
0x08048514 <+68>: cmp 0xc(%ebp),%eax
0x08048517 <+71>: setl %al
0x0804851a <+74>: test %al,%al
0x0804851c <+76>: jne 0x80484df <_Z4initP21xuzhina_dump_c05_s3_3i+15>
0x0804851e <+78>: leave
0x0804851f <+79>: ret
End of assembler dump.
(gdb) disassemble sum
Dump of assembler code for function _Z3sumP21xuzhina_dump_c05_s3_3i:
0x08048520 <+0>: push %ebp
0x08048521 <+1>: mov %esp,%ebp
0x08048523 <+3>: sub $0x10,%esp
0x08048526 <+6>: movl $0x0,-0x4(%ebp) ;sum
0x0804852d <+13>: movl $0x0,-0x8(%ebp) ;i
0x08048534 <+20>: jmp 0x804854f <_Z3sumP21xuzhina_dump_c05_s3_3i+47>
0x08048536 <+22>: mov -0x8(%ebp),%eax ;i
0x08048539 <+25>: lea 0x0(,%eax,8),%edx
0x08048540 <+32>: mov 0x8(%ebp),%eax ;test
0x08048543 <+35>: add %edx,%eax
0x08048545 <+37>: mov 0x4(%eax),%eax ;test[i].sq
0x08048548 <+40>: add %eax,-0x4(%ebp)
0x0804854b <+43>: addl $0x1,-0x8(%ebp) ;i++
0x0804854f <+47>: mov -0x8(%ebp),%eax
0x08048552 <+50>: cmp 0xc(%ebp),%eax ;i < n
0x08048555 <+53>: setl %al
0x08048558 <+56>: test %al,%al
0x0804855a <+58>: jne 0x8048536 <_Z3sumP21xuzhina_dump_c05_s3_3i+22>
0x0804855c <+60>: mov -0x4(%ebp),%eax
0x0804855f <+63>: leave
0x08048560 <+64>: ret
End of assembler dump.
从上面的汇编,结构体数组的特征如下:
1. 先是找到数组的首地址
2. 再根据索引找到每个元素,得到每个元素的地址。
3. 再以每个元素的地址作为结构体基址,再获取成员变量的地址。