结构体的sizeof问题

whhqlxz 2012-02-19 12:36:23
作者:武汉华嵌嵌入式培训学院 技术部

引言:在很多项目开发过程以及诸多名企入职笔试题里面都有对结构体求sizeof的问题,武汉华嵌结合教学和研发实践,总结了一下几点,希望可以为大家提供有效参考。



sizeof有三种语法形式,如下:
ⅰ、sizeof(object_name); //sizeof(对象);

ⅱ、sizeof(type_name); //sizeof(类型);

ⅲ、sizeof object_name; //sizeof 对象;


注意:sizeof是一个运算符,在C语言中是一个关键字,并不是函数,要和strlen区分开来。sizeof是求取所占的存储空间的所有字节数。

sizeof与结构体的使用,先来看下面的例子:
typedef struct
{
int a;
char b;
}A_t;
typedef struct
{
int a;
char b;
char c;
}B_t;
typedef struct
{
char a;
int b;
char c;
}C_t;
int main(int argc, char *argv[])
{
char *a=0;
printf(“%d\n”, sizeof(a)); //输出结果:4
printf(“%d\n”, sizeof(*a)); //输出结果:1
printf(“%d\n”, sizeof(A_t)); //输出结果:8
printf(“%d\n”, sizeof(B_t)); //输出结果:8
printf(“%d\n”, sizeof(C_t)); //输出结果:1

return 0;
}


为什么会有如上的结果呢?这和字节对齐有关,当然还和硬件平台有关,也和编译器有关。就一般情况而言,主要有以下三个原则:

1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,
如有需要编译器会在成员之间加上填充字节(internal adding);
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最
末一个成员之后加上填充字节(trailing padding)。

在字节对齐的时候有的时候是需要字节填充的,那这是为什么呢?大家不防想一想,在C语言中基本的数据类型都有一定的存储大小,那么来看一下下面的这个例子:

struct stu{
char a;
int b;
};
假设int类型占有4个字节的大小,则sizeof(struct stu)的大小就为8,根据上面的三条分析和基本类型的存储宽度可知,在成员a的后面会补上三个字节,然后才存放成员b,即总共占了8个字节。

sizeof和含有位域的结构体的使用:
位域成员不能单独被取sizeof值,我们这里要讨论的是含有位域的结构体的sizeof,只是考虑到其特殊性而将其专门列了出来。
C99规定int、unsigned int和bool可以作为位域类型,但编译器几乎都对此作了扩展,
允许其它类型类型的存在。
使用位域的主要目的是压缩存储,其大致规则为:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字
段将紧邻前一个字段存储,直到不能容纳为止;
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字
段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++采取压缩方式;
4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。

让我们来看如下的例子:
struct stu{
char a:3;
char b:4;
char c:5;
};

则sizeof(struct stu)的大小在gcc上面得到的结果为2,在visual c上得到的结果也为2。根据以上五条,还有前面讲的对齐,可以得出结果为2个字节。我们再来看下如下的例子:

struct stu{
char a:3;
int b:4;
char c:5;
};
则sizeof(struct stu)的大小在gcc上面得到的结果为4,在visual c上得到的结果为12。根据以上五条,还有前面讲的对齐,可以推出这样的结果,请着重看下第三条,就可以知道visual c和gcc分别得到不同结果的原因了。



(本文为武汉华嵌嵌入式培训所创,转载请注明来源)
...全文
183 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
tanglinux 2012-03-31
  • 打赏
  • 举报
回复
man数组的每个元素都是指针变量,在32位机,当然是12,这里没有所谓的填充,与结构体是完全不同的概念。

[Quote=引用 10 楼 的回复:]

引用 9 楼 wanghb1989 的回复:
能解释一下char *man[]={“wan”,“w”,“a”}为什么是12呢?难道不能使用字符填充吗?

相当于数组char man[3][4],因此为12
[/Quote]
海子0011 2012-03-17
  • 打赏
  • 举报
回复
是的,最后一个是12,应该是楼主笔误。
xuexingyang 2012-03-13
  • 打赏
  • 举报
回复
是的,最后一个是12,应该是楼主笔误。
huang_vincent 2012-03-12
  • 打赏
  • 举报
回复
printf(“%d\n”, sizeof(a)); //输出结果:4
printf(“%d\n”, sizeof(*a)); //输出结果:1
printf(“%d\n”, sizeof(A_t)); //输出结果:8
printf(“%d\n”, sizeof(B_t)); //输出结果:8
printf(“%d\n”, sizeof(C_t)); //输出结果:1

最后一个printf好像有点问题吧。。。。
怎么可能是1呢?不应该是12吗??、
www_555 2012-03-12
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 wanghb1989 的回复:]
能解释一下char *man[]={“wan”,“w”,“a”}为什么是12呢?难道不能使用字符填充吗?
[/Quote]
相当于数组char man[3][4],因此为12
wanghb1989 2012-03-11
  • 打赏
  • 举报
回复
能解释一下char *man[]={“wan”,“w”,“a”}为什么是12呢?难道不能使用字符填充吗?
nijiama123 2012-03-09
  • 打赏
  • 举报
回复
printf(“%d\n”, sizeof(C_t)); //输出结果:1
错了,输出结果是12
lbmygf 2012-03-09
  • 打赏
  • 举报
回复
duloveding 2012-02-21
  • 打赏
  • 举报
回复
不错。看标题以为要问问题呢!支持!
gududesiling 2012-02-21
  • 打赏
  • 举报
回复

早一点看到就好了


?为什么早点看就好了
liujwcool1 2012-02-20
  • 打赏
  • 举报
回复
早一点看到就好了
liujwcool1 2012-02-20
  • 打赏
  • 举报
回复
早一点看到就好了
dongjiawei316 2012-02-19
  • 打赏
  • 举报
回复
学习了。。。

21,597

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧