日期:2014-05-16 浏览次数:20946 次
在C语言里,结构体是不同类型数据结构的集合。由于结构体比较复杂,分为几种情况来讨论:
1. 成员全是由基本数据类型构成
2. 成员有基本数据类型,也有其它结构体构成,构成成员的结构体是1,2两种情况。
3. 结构体构成的数组
这一节先讨论第一种情况.要了解这种类型结构体的内存布局,首先要知道成员在内存里是如何排序,及各个成员在内存占的大小。先看一个例子
#include <stdio.h>
struct xuzhina_dump_c05_s3_stru
{
char a;
short b;
int c;
long d;
float e;
double f;
void* g;
};
int main()
{
struct xuzhina_dump_c05_s3_stru test;
printf( "addr:%x, 1st:%x, 2nd:%x, 3rd:%x, 4th:%x, 5th:%x, 6th:%x, 7th:%x
",
&test, &test.a, &test.b, &test.c, &test.d, &test.e, &test.f, &te
st.g );
return 0;
}
运行结果:
addr:bf909eb4, 1st:bf909eb4, 2nd:bf909eb6, 3rd:bf909eb8, 4th:bf909ebc, 5th:bf909ec0, 6th:bf909ec4, 7th:bf909ecc
可得这样的结论:
1. 结构体对象的地址和第一个成员地址一样。也就是所谓的基地址
2. 第一个成员a和第二个成员b分别是char,short,不足dword大小,为了内存对齐,挤一个dword里。int, long, float, double,指针由于大小分别是4,4,4,8,4,直接按照4字节进行内存对齐,也分别占4,4,4,8,4个字节的空间.
3. 各个成员还是按照结构体的声明顺序由低到高排列。
4. 每个成员的地址都是它前面所有成员的大小(包括内存对齐)和基地址的累加。像test.d的地址就是bf909eb4+0x8 = bf909ebc.它前面的成员a ,b在一个dword, c占一个dword,刚好是8.
可能成员类型会由于内存对齐而分辨不出来。其实,用5.1节的方法是可以分辨得出来。有兴趣可以尝试一下。
那么一个结构体如何从汇编里识别出来呢,它究竟有什么特征?
先看一下这个例子。
struct xuzhina_dump_c05_s3_stru
{
char a;
short b;
int c;
};
bool equal( struct xuzhina_dump_c05_s3_stru* first,
struct xuzhina_dump_c05_s3_stru* second )
{
if ( first->a != second->a )
{
return false;
}
if ( first->b != second->b )
{
return false;
}
if ( first->c != second->c )
{
return false;
}
return true;
}
int main()
{
struct xuzhina_dump_c05_s3_stru first = { 'a', 10, 20 };
struct xuzhina_dump_c05_s3_stru second = {'a', 10, 21 };
if ( equal( &first, &second ) )
{
return 0;
}
return 1;
}
汇编代码
(gdb) disassemble equal
Dump of assembler code for function _Z5equalP24xuzhina_dump_c05_s3_struS0_:
0x08048470 <+0>: push %ebp
0x08048471 <+1>: mov %esp,%ebp
0x08048473 <+3>: mov 0x8(%ebp),%eax
0x08048476 <+6>: movzbl (%eax),%edx
0x08048479 <+9>: mov 0xc(%ebp),%eax
0x0804847c <+12>: movzbl (%eax),%eax
0x0804847f <+15>: cmp %al,%dl
0x08048481 <+17>: je 0x804848a <_Z5equalP24xuzhina_dump_c05_s3_struS0_+26>
0x08048483 <+19>: mov $0x0,%eax
0x08048488 <+24>: jmp 0x80484c0 <_Z5equalP24xuzhina_dump_c05_s3_struS0_+80>
0x0804848a <+26>: mov 0x8(%ebp),%eax
0x0804848d <+29>: movzwl 0x2(%eax),%edx
0x08048491 <+33>: mov 0xc(%ebp),%eax
0x08048494 <+36>: movzwl 0x2(%eax),%eax
0x08048498 <+40>: cmp %ax,%dx
0x0804849b <+43>: je 0x80484a4 <_Z5equalP24xuzhina_dump_c05_s3_struS0_+52>
0x0804849d <+45>: mov $0x0,%eax
0x080484a2 <+50>: jmp 0x80484c0 <_Z5equalP24xuzhina_dump_c05_s3_struS0_+80>
0x080484a4 <+52>: mov 0x8(%ebp),%eax
0x080484a7 <+55>: mov 0x4(%eax),%edx
0x080484aa <+58>: mov 0xc(%ebp),%eax
0x080484ad <+61>: mov 0x4(%eax),%eax
0x080484b0 <+64>: cmp %eax,%edx
0x080484b2 <+66>: je 0x80484bb <_Z5equalP24xuzhina_dump_c05_s3_struS0_+75>
0x080484b4 <+68>: mov