本文是我在阅读了“ 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
请