温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

【C深度剖析】sizeof操作符与数组

发布时间:2020-06-27 00:23:54 来源:网络 阅读:2295 作者:沃特water 栏目:系统运维

sizeof操作符与数组

一、  sizeof是何方神圣

说到sizeof,首先必须知道的一点:sizeof不是函数,sizeof是操作符。sizeof的作用就是,计算一个对象或类型所占的内存字节数。


  1.1 sizeof的语法

        sizeof()

这也正是为什么sizeof会有那么多人误解其为函数。括号里面可以是一个数据对象,也可以是一个数据类型。对于有括号的这种语法来说,你大可以不用理会括号里面是一个数据类型还是一个数据对象。

sizeof object:

初次见面,以为是语法错误,其实这也是sizeof的一种用法,计算数据对象所占的内存字节数。如果计算的是一个数据类型,那么请用上面的括号形式。如此看来,那么多程序员使用()的语法形式是有道理的,因为放之四海皆准。


1.2 sizeof如何计算大小

如果你学习过JAVA,那么你会发现,JAVA中根本不存在sizeof操作符。难道是因为JAVA不够完善吗?其实不然。JAVA之所以没有sizeof操作符,也正如JAVA设计者所言:JAVA不需要sizeofJAVA的运行时需要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当做一个指针,指针的内存在所占的字节数为412则是把数组名看做一种数据结构,这个数据结构的大小为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操作符搭配的时候,其表现也并不简单,其依然还是保留了数组名作为一种数据结构的特性。



向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI