热爱软件过程

对c/c++的热爱犹如对美女的热爱

 

C/C+语言struct再深层探索(原创)

C/C+语言struct再深层探索(原创)  

作者:    ehhboy                                 日期: 2005-11-2

1.       struct的巨大作用:

在宋保华的文章中已经说明.

2.       结构体的问题:

对于程序员来说,常常遇到结构体的处理问题,如初始化结构体变量,对结构体变量赋值问题.不知大家常常怎么进行,我曾经任务直接memset(结构体变量,…) 会出现不可预知的问题,后来觉得结构体变量空间应该是逻辑上是顺序的,就开始大胆使用,然而对memcpy还是谨慎使用,更不敢使用直接赋值方式.不知大家遇到这种问题怎么处理.

3.       也谈结构体成员的对齐:

在宋宝华的文章中提到:

自然对界

struct是一种复合数据类型,其构成元素既可以是基本数据类型(如intlongfloat等)的变量,也可以是一些复合数据类型(如arraystructunion等)的数据单元。对于结构体,编译器会自动进行成员变量的对齐,以提高运算效率。缺省情况下,编译器为结构体的每个成员按其自然对界(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位也空出一个自己,这是才发现是:
结构体中字符串的真正长度是自然对界的长度的整数倍
,如过不足补齐处理.

 

 

posted on 2005-11-02 14:49 逗泥丸 阅读(293) 评论(0)  编辑 收藏 引用 所属分类: 技术感悟

导航

统计

常用链接

留言簿

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论