重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
sizeof操作符与数组
创新互联建站2013年至今,是专业互联网技术服务公司,拥有项目网站建设、网站设计网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元凭祥做网站,已为上家服务,为凭祥各地企业和个人服务,联系电话:18980820575
一、 sizeof是何方神圣
说到sizeof,首先必须知道的一点:sizeof不是函数,sizeof是操作符。sizeof的作用就是,计算一个对象或类型所占的内存字节数。
1.1 sizeof的语法
sizeof():
这也正是为什么sizeof会有那么多人误解其为函数。括号里面可以是一个数据对象,也可以是一个数据类型。对于有括号的这种语法来说,你大可以不用理会括号里面是一个数据类型还是一个数据对象。
sizeof object:
初次见面,以为是语法错误,其实这也是sizeof的一种用法,计算数据对象所占的内存字节数。如果计算的是一个数据类型,那么请用上面的括号形式。如此看来,那么多程序员使用()的语法形式是有道理的,因为放之四海皆准。
1.2 sizeof如何计算大小
如果你学习过JAVA,那么你会发现,JAVA中根本不存在sizeof操作符。难道是因为JAVA不够完善吗?其实不然。JAVA之所以没有sizeof操作符,也正如JAVA设计者所言:JAVA不需要sizeof。JAVA的运行时需要JVM的,不同的操作系统都有对应的JVM,在JVM中保证了所有类型的大小一致,不管你运行在32位还是64位的机器上,数据类型的大小都是已知的,这也正是JAVA可移植性能够实现的最根本的原因。回到话题来,为什么C/C++需要sizeof?显然,对于一个合格的C程序员,我们应该知道,我们所写的程序运行在不同结构的机器上的时候,类型的大小有所区别。当我们需要知道一个类型的大小才能继续写程序的时候,我们就需要sizeof。这就是为什么我们需要sizeof。
二、 数组并没有那么简单
数组和指针是C语言中的重头戏,那么数组是什么数据类型呢?按照其他书籍的介绍,数组是复合类型(与基本数据类型结合构成的类型)。数组是同一类型的数据的集合,在内存中的表现为一串连续的内存,内存的大小为单个数据类型的大小与数据量的乘积。在我个人看来,数组更应该称为数据结构。数据结构中的顺序表,其实现的核心就是数组。由此可见,数组更像是一种C语言预先定义的数据结构。
2.1 数组的语法
数据类型 数组名[数据个数]
倘若我们在定义的时候就初始化,那么数组中第一个维度的数据大小可以不写。
2.2 数组名到底是什么
数组名是一段内存空间的名字,其指向了这段内存空间。我们讲到了sizeof,那么sizeof(数组名)计算出来的,理所应当计算的就是数组名指向的这段内存空间的字节数,事实也正是如此。但是,当我们对数组名继续深究下去,我们就会开始对sizeof(数组名)疑惑了。看下面的例子:
int arr[3] = {0,1,2}; printf(“%p”,arr);
上面的例子,打印的将会是数组首元素的地址。由此我们可以推测:arr是一个指针。我们这么推测是有理由的,因为指针才能存储一个地址。但是倘若我们想现在下定论,就需要考虑sizeof(arr)。这时候你再来回答,sizeof(arr)的大小是多少。两种答案:4或者12。答案是4的显示,我们把arr当做一个指针,指针的内存在所占的字节数为4;12则是把数组名看做一种数据结构,这个数据结构的大小为12字节。正确答案大家知道是12。到这里我们的疑惑就更深了,既然编译器认为arr不是指针,但是arr在打印地址的时候,又保存了一个地址。这就是我们需要说的:数组名是一个类似于指针的数据结构变量名。在普通情况下,我们可以把数组名当做指针来使用。继续看下面的一个例子:
int arr[3] = {0,1,2}; int arr2[3] = {3,4,5}; arr= arr2;
上面的代码我们想完成的事情是将arr2数组赋值给arr数组,但是编译的时候是错误的,因为arr在表现为指针属性的时候,实际上是一个常量指针。我们不会对一个已经初始化了的变量再次赋值。
2.3 数组作为函数参数
当数组作为函数形参的时候,数组名则沦为指针,既然是一个指针,我们就可以对其自增、自减和修改。在函数体内,数组名仅仅作为一个数组的指针。我们知道了他是指针,只要我们搞清楚这个指针实际指向的数据类型,那么对于指针的使用就显得简单了。
三、 sizeof与数组
看下面的一段代码:
int arr[2][2] = { {0,1}, {2,3} }; printf(“%d,”,sizeof(arr)); printf(“%d,”,sizeof(arr[0])); printf(“%d\n”,sizeof(arr[0][0]));
三个printf将会打印什么?答案:16,8,4
3.1 sizeof(arr)
弄清楚答案的缘由我们先了解一下多维数组。
C/C++中,多维数组实际上是一位数组。多维数组在分配内存的时候,是分配一段完整的连续的内存空间。这么说可能理解不深刻。我们先来了解一下JAVA中的多维数组,就以二维数组来看。JAVA中的二维数组在分配空间的时候,首先会分配一个大小为2的数组,其保存的是2个一维数组的起始地址。这两个一维数组在内存上并不一定是连续的。再看看C中的数组,就能理解其完整的连续的意思。
正是因为如此,所以sizeof(arr)才会打印16。因为sizeof计算的是数组名对应的内存空间的大小,不管维度大小。
3.2 sizeof(arr[0])
接下来我们看一下sizeof(arr[0])。如果外面没有sizeof操作符,arr[0]在此处如果换成指针来看待,其运算如下:(arr + 0 ),其指向的依然是数组的首行首元素的地址。但是在sizeof操作符下,arr[0]显然不能够当做指针来看待,这时应该理解为二维数组的一维数组(逻辑上是如此,实际上多维数组还是一位数组)。arr[0]指向的是第一行的一位数组,我们可以理解为arr[0]就是一个数组名,其内存空间为arr数组的前2个元素对应的内存空间,我们sizeof,得到的结果就应该为8。
3.2 sizeof(arr[0][0])
最后来看sizeof(arr[0][0]),arr[0][0]表示访问的是二维数组的首行一维数组的首元素,其变量就是一个int类型,所以结果为4。
由此看来,数组名与sizeof操作符搭配的时候,其表现也并不简单,其依然还是保留了数组名作为一种数据结构的特性。