结合sizeof浅谈C++中的指针和字节对齐

本文探讨了C++中的sizeof运算符、指针和字节对齐的概念。通过实例分析了sizeof与指针、数组交互时的结果,并详细解释了字节对齐的原则和在类大小计算中的影响。此外,还讨论了虚函数、继承和虚拟继承对类大小的影响。
摘要由CSDN通过智能技术生成

本文是我在阅读了“ sizeof用法”(http://blog.csdn.net/ymd378362996/article/details/7634343 )、“c++字节对齐与结构体大小”(http://pppboy.blog.163.com/blog/static/30203796201082494026399/)以及“转载学习结构体和union大小的问题”(http://blog.csdn.net/vincent_1011/article/details/4479965)后,经过自己一番实践之后写的,主要是记录并分享一下心得与收获,有不正确的地方欢迎指正交流。本文中有部分内容源自以上三篇文章。


先说说sizeof,sizeof是C语言的一种单目操作符(但有人也不这么以为,认为它是一种特殊的宏),如C语言的其他操作符++、--等。它并不是函数(这是必须的)。sizeof操作符以字节形式给出了其操作数的存储大小。操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型决定,简单的说其作用就是返回一个对象或者类型所占的内存字节数。而且,sizeof在程序编译阶段就会被处理,因此在sizeof作用域范围内的表达式,也就是sizeof()括号内的表达式也不能被编译,而是被转换成相应的类型。

例如:

int a=0;
cout<<sizeof(a=3)<<endl;
cout<<a<<endl;
该段程序执行后,a的值仍然保持为0,因为由于=操作符返回操作符左边的数据类型,所以在编译阶段,sizeof(a=3)等价于sizeof(int),而这个赋值操作由于未被系统实际执行,所以a的值没有改变。

更多有关sizeof的特性可以参看我在前面给出的文章。


在sizeof的实际使用中,像sizeof(int),sizeof(char)等等简单的运用往往不是最令人头疼的。但当sizeof和指针、数组打交道的时候,结果往往与我们所预想的不同,接下来就让我们一步步探索。


首先说明,我用的虽然是64位系统,但操作系统分配的地址仍然是32位,因此任何类型的指针的长度都将是4个字节。

还要说明的是,本文中将数组名理解为一种独特的数据类型,而非一个常量指针,具体可以参考:http://blog.csdn.net/yby4769250/article/details/7294718


根据我自己的理解:当我们声明变量 int a 时,a代表一个int类型的数据,而“a”这个标识符则是这个数据的“名称”,标识符“a”不占空间,而在编译成汇编代码的时候,“a”将被替换成该int类型数据的地址。所以当我们声明数组 int b[5] 的时候,相当于声明 int[5] b, b代表一个int[5]类型的数据,而“b”是这个数据的名称,“b”不占空间,不是大多数人所说的“常量指针”(所以当你对数组名取址时,编译是不通过的),在编译阶段,对数组的操作将转换为对数组首位地址+偏移量的操作。因此,当对数组名使用sizeof的时候,我们就可以正确得到数组的大小,至于 *b == &b[0],个人推测是为了方便程序员对数组进行操作,c++将*操作符对数组名这一类数据类型进行了重载。


接下来进入正题:


从最简单的开始:

double a[5] ;
cout << "size of a:" <<sizeof(a)<< endl;
cout << "size of *a:" << sizeof(*a) << endl;

输出:


size of a:40
size of *a:8
请按任意键继续. . .


a是一个double类型的数组,长度为5,则sizeof(a) 等价于sizeof(double[5]) = 5*8 = 40,而sizeof(*a)相当于sizeof(double) = 8



接下来考虑 double *a[5]

double *a[5];
cout << "size of a:" <<sizeof(a)<< endl;
cout << "size of *a:" << sizeof(*a) << endl;
cout << "size of **a:" << sizeof(**a) << endl;</span>


输出: 

size of a:20
size of *a:4
size of **a:8
请按任意键继续. . .


从输出结果可以看出,* 优先与[5]结合,即形成的数组是一个指针数组,里面存储着 double*类型的元素,而a则是这个数组的数组名。

因此,sizeof(a) = sizeof ( double *[5] ) = 5 * sizeof(double *) = 5 * 4 = 20,

sizeof(*a) = sizeof(double *) = 4,sizeof(**a) = sizeof(double) = 8 



上面的代码中,* 优先和数组内的元素进行了结合,接下来我们改变一下优先级,让 * 与 数组名优先结合。

double (*a)[5];
cout << "size of a:" <<sizeof(a)<< endl;
cout << "size of *a:" << sizeof(*a) << endl;
cout << "size of **a:" << sizeof(**a) << endl;</span></span></span>

输出结果:

size of a:4
size of *a:40
size of **a:8

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值