在探究过数组和结构体这两种非原生的数据类型之后,可能会想知道这两种类型结合成结构体数组,会有什么特征。
先看一个例子:
#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. 再以每个元素的地址作为结构体基址,再获取成员变量的地址。