C/C+语言struct再深层探索(原创)
作者: ehhboy 日期: 2005-11-2
1. struct的巨大作用:
在宋保华的文章中已经说明.
2. 结构体的问题:
对于程序员来说,常常遇到结构体的处理问题,如初始化结构体变量,对结构体变量赋值问题.不知大家常常怎么进行,我曾经任务直接memset(结构体变量,…) 会出现不可预知的问题,后来觉得结构体变量空间应该是逻辑上是顺序的,就开始大胆使用,然而对memcpy还是谨慎使用,更不敢使用直接赋值方式.不知大家遇到这种问题怎么处理.
3. 也谈结构体成员的对齐:
在宋宝华的文章中提到:
自然对界
struct是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如array、struct、union等)的数据单元。对于结构体,编译器会自动进行成员变量的对齐,以提高运算效率。缺省情况下,编译器为结构体的每个成员按其自然对界(natural alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。
自然对界(natural alignment)即默认对齐方式,是指按结构体的成员中size最大的成员对齐。
指定对界
一般地,可以通过下面的方法来改变缺省的对界条件:
· 使用伪指令#pragma pack (n),编译器将按照n个字节对齐;
· 使用伪指令#pragma pack (),取消自定义字节对齐方式。
注意:如果#pragma pack (n)中指定的n大于结构体中最大成员的size,则其不起作用,结构体仍然按照size最大的成员进行对界。
下面我谈谈他没有明确指出的两点
n 首先指出n 的取值范围:1,2,4,8,16;
n 接着举例说明自然对齐中字符串对齐方式:
如结构体: struct EX
{
char a[100];
long c;
char b;
char * p;
} ;
问题发现过程: 在32位环境下long的长度是4个字节,字符指针长度也是4个字节所以根据自然对界其长度为EX长度是112;然而在64位环境下long的长度是8个字节,字符指针长度也是8个字节,所以应该是124个字节,然而运行的结果却不是,而是128.
为了探个究竟,编写下列程序输出内存结果:
main()
{
char ll[2];
strcpy( ll, "2" );
struct EX ex,ex2,ex3;
memset( &ex, '\0', sizeof( ex ) );
memset( &ex2, '\0', sizeof( ex2 ) );
memset( &ex3, '\0', sizeof( ex3 ) );
ex.a[0] = '1';
ex.a[99] ='9';
ex.c = 0XFFFFFFFFFFFFFFFF;
dmpvarX( &ex, sizeof( ex ) );
/* ex2= ex;
dmpvarX( &ex2, sizeof( ex2 ) );
memcpy( &ex3, &ex, sizeof( ex3) );
dmpvarX( &ex3, sizeof( ex3 ) );
*/
printf( " size [%d]\n", sizeof( ex.a ) );
printf( " size [%d]\n", sizeof( ex.c ) );
printf( " size [%d]\n", sizeof( ex.b ) );
printf( " size [%d]\n", sizeof( ex.p ) );
printf( " size [%d]\n", sizeof( ex ) );
}
/* 用于打印内存 */
int dmpvarX( void * p, int len )
{
int i;
int blen = 8;
char cstr[2*8+1];
char c;
for( i=0; i/(2*blen)<=(len-1)/(2*blen) ; i++ )
{
if( i
{
if( i%(2*blen) == 0 )
memset( cstr, '\0', sizeof( cstr ) );
c = ( (char *)p )[i];
printf("%02x ", (short)c );
if ( isprint( c ) ) cstr[i%(2*blen)] = c;
else cstr[i%(2*8)] ='.';
}
else printf( " " );
if( (i+1)%blen == 0) printf(" " );
if( (i+1)%blen == 0) printf(" " );
if( (i+1)%(2*blen) == 0) {
printf("%-16s", cstr );
printf("\n" );
}
}
return 0;
}
在64位环境下编译运行得到:
31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1...............
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 39 00 00 00 00 ff ff ff ff ff ff ff ff ...9............
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
size [100]
size [8]
size [1]
size [8]
size [128]
发现整数前面空出四个字节, 后来把字符串a定义位99发现空出来5个字节,对于32位也空出一个自己,这是才发现是:
结构体中字符串的真正长度是自然对界的长度的整数倍,如过不足补齐处理.