Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1781042
  • 博文数量: 413
  • 博客积分: 8399
  • 博客等级: 中将
  • 技术积分: 4325
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-09 10:44
文章分类

全部博文(413)

文章存档

2015年(1)

2014年(18)

2013年(39)

2012年(163)

2011年(192)

分类: C/C++

2011-11-21 17:08:11

在CU的C/C++版看到一个例子:
  1. #include <stdio.h>

  2. struct A{
  3.         char a;
  4.         char b;
  5.         int c[0];
  6. };

  7. struct B{
  8.         char a;
  9.         char b;
  10.         int c;
  11. };

  12. int main()
  13. {
  14.         printf("sizeof(struct A): %d\n", sizeof(struct A));
  15.         printf("sizeof(struct B): %d\n", sizeof(struct B));

  16.         return 0;
  17. }
结果:
  1. digdeep@ubuntu:~/uulp$ gcc -Wall -o sizeof sizeof.c
  2. digdeep@ubuntu:~/uulp$ ./sizeof
  3. sizeof(struct A): 4
  4. sizeof(struct B): 8
  5. digdeep@ubuntu:~/uulp$
C语言在编译时的对齐规则:
1)找出struct 结果体中占用内存最大的类型(__alignof__(type)最大的类型),在struct A,struct B中都是int。
2)知道常识:编译指标器(#pragma pack(X),x86机器上默认X一般是4。
3)机器字长 (32位/64位)
注:有个容易误解的地方,占用内存最大的类型,不是指sizeof最大的那个,而是指__alignof__(type)最大的那个,double在32位上,可以为4和8,默认为4,可由编译参数控制,如果编译时加上-malign-double__aignof__(double)值由4变成了8。(一般除了double之外,其它的类型sizeof(type)  == __alignof__(type) )

比较三者,按照三者中
的来对齐。
因为__alignof__(int) == sizeof(int) == 4,所以struct A和struct B都是按照4字节对齐。
所以:sizeof(struct A) == 4, sizeof(struct B) == 8
在struct A中应该说int c[0]并不占用内存。也就是0长度的数组不占内存。
但是:数组长度虽然为0,但是却影响了结构体整体的对齐

一个类型的对齐值,可通过操作符__alignof__(type)得到
struct A{
      char a;
      char b;
      int a[0];
};
在编译器默认对齐方式的情况下,结构体内成员所在位置必须为其自身类型的整数倍,即short型必须在__aignof__(short) * n == 2n 的位置上开始存储。int 型必须在__aignof__(int)*n == 4n,double型必须在__aignof__(double)*n ==4n != 8n的位置上开始存储。而对于0长数组的情况,这个数组只是看上去在结构体里面,实际上并不能算是结构体的正式成员。
但是我们使用他的时候需要把他当做结构体的成员使用。

结构体 struct A 当中,由于最后一个成员是int c[0], 在为结构体分配空间时,按照int 类型对齐
假设 A.a地址为0xbfd1c, 则A.b地址为0xbfd1d, 则数组c的起始地址为0xbfd1d往后2位(按照int类型对齐),即为0xbfd20,但是c[0]不分配空间不占空间所以sizeof(A)=4
示例:
  1. #include <stdio.h>

  2. struct A{
  3.         char a;
  4.         char b;
  5.         double d;
  6. };

  7. int main()
  8. {
  9.         printf("sizeof(struct A): %d\n", sizeof(struct A));
  10.         return 0;
  11. }
编译运行结果:
  1. digdeep@ubuntu:~/uulp$ gcc -Wall -o sizeof sizeof.c
  2. digdeep@ubuntu:~/uulp$ ./sizeof
  3. sizeof(struct A): 12
  4. digdeep@ubuntu:~/uulp$ gcc -Wall -malign-double -o sizeof sizeof.c
  5. digdeep@ubuntu:~/uulp$ ./sizeof
  6. sizeof(struct A): 16
  7. digdeep@ubuntu:~/uulp$
可以看出,加了 -malign-double 选项时,结果为16,没有加 -malign-double 选项时,结果为12.
加了 -malign-double 选项时,强调按照double的sizeof(double)的大小来对齐。


在看一看几个例子:
  1. #include <stdio.h>

  2. struct A{
  3.         char a;
  4.         char b;
  5. };

  6. struct B{
  7.         char a;
  8.         char b;
  9.         double c;
  10. };

  11. struct C{
  12.         char a;
  13. };

  14. struct D{
  15.         char a;
  16.         short c[0];
  17. };

  18. struct E{
  19.         char a;
  20.         int c[0];
  21. };

  22. int main()
  23. {
  24.         printf("sizeof(struct A): %d\n", sizeof(struct A));
  25.         printf("sizeof(struct B): %d\n", sizeof(struct B));
  26.         printf("sizeof(struct C): %d\n", sizeof(struct C));
  27.         printf("sizeof(struct D): %d\n", sizeof(struct D));
  28.         printf("sizeof(struct E): %d\n", sizeof(struct E));

  29.         return 0;
  30. }
结果:
  1. digdeep@ubuntu:~/uulp$ gcc -Wall -o sizeof2 sizeof2.c
  2. digdeep@ubuntu:~/uulp$ ./sizeof2
  3. sizeof(struct A): 2
  4. sizeof(struct B): 12
  5. sizeof(struct C): 1
  6. sizeof(struct D): 2
  7. sizeof(struct E): 4

看到另一个与sizeof相关的问题:

2.某32位系统下, C++程序,请计算sizeof 的值(5分).
char str[] = “
char *p = str ;
int n = 10;
请计算
sizeof (str ) = ?(1)
sizeof ( p ) = ?(2)
sizeof ( n ) = ?(3)
void Foo ( char str[100]){
请计算
sizeof( str ) = ?(4)
}
void *p = malloc( 100 );
请计算
sizeof ( p ) = ?(5)

答:(1)25 (2)4 (3) 4 (4)4 (5)4
此题的关键是看:sizeof() 计算的到底是什么类型的变量的大小!!!
第一个sizeof(str),很明显str是将一个字符赋值给一个字符数组,所以答案应该是数组的大小。是25而不是24,因为最后还有结尾符:‘/0‘
第二个sizeof(p),很明显p是一个指针,所以在32为机器上大小为4字节
第三个sizeof(n),很简单,32为机器上int为4字节
第四个sizeof(str),应该注意该"str"是一个参数,我们知道C中数组作为参数,实际上传递的是数组的第一个元素的地址,所以"str"是一个指针,所以sizeof(str)等于4
第五个sizeof(p),p也是指针,所以大小为4.

这里特别要注意的是第一个和第四个!
第一个等于25而不是24要特别注意,因为是将一个字符串赋值给字符数组,而字符串是有结尾符的!!!
看下面代码的运行结果:
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. void foo(char str[100])
  4. {
  5.         printf("sizeof(str3): %d\n", sizeof(str));
  6. }

  7. int main()
  8. {
  9.         char str[] = "";
  10.         char str2[] = {'h', 't', 't','p',':','/','/',
  11.                         'w','w','w','.','i','b','e','g','r','o','u','p',
  12.                         '.','c','o','m','/'};
  13.         char *p = str ;
  14.         int n = 10;
  15.         void *p1 = malloc(100);

  16.         printf("sizeof(str): %d\n", sizeof(str));
  17.         printf("sizeof(str2): %d\n", sizeof(str2));
  18.         printf("sizeof(p): %d\n", sizeof(p));
  19.         printf("sizeof(n): %d\n", sizeof(n));
  20.         printf("sizeof(p1): %d\n", sizeof(p1));
  21.         foo(str);

  22.         return 0;
  23. }
运行结果:
  1. digdeep@ubuntu:~/uulp$ ./sizeof
  2. sizeof(str): 25
  3. sizeof(str2): 24
  4. sizeof(p): 4
  5. sizeof(n): 4
  6. sizeof(p1): 4
  7. sizeof(str3): 4


阅读(2312) | 评论(4) | 转发(0) |
给主人留下些什么吧!~~

digdeep1262011-11-22 21:02:14

4 + 8 (sizeof(double) == 8)

suanmeilizhi2011-11-22 18:55:12

lz,struct B为啥是12?

digdeep1262011-11-22 12:43:08

能让读者感到有所收获,是一件令人十分高兴的事情。

星期五啦2011-11-22 09:18:12

恩,LZ讲的很精辟很到位啊!
令俺瞬间了解了sizeof函数的原理和用法,进一步认识了关于结构体的空间分配问题,受教受教了!