目录
创作不易,如对您有帮助,还望一键三连,谢谢!!!
1.sizeof和strlen的对比
1.1sizeof
1.2strlen
1.3sizeof和strlen对比
2.数组笔试题讲解
数组名的理解
2.1一维数组
2.2字符数组
题目一:
题目二:
题目三:
2.3二维数组
创作不易,如对您有帮助,还望一键三连,谢谢!!!
今天我们来讲一些数组和指针经典的笔试题。而在讲解这些题目之前,我们得先来回忆一下sizeof和strlen。
1.sizeof和strlen的对比
1.1sizeof
在学习操作符的时候,我们学习了 sizeof , sizeof 计算变量所占内存内存空间大小的,单位是
字节,如果操作数是类型的话,计算的是使⽤类型创建的变量所占内存空间的大小。
注意:sizeof只关注占用内存的大小,并不关注内存中存放的是什么数据。
我们来看下面这段代码:
这段代码运行结果如下:
这个结果验证了上面我们所说的sizeof只关注占用内存空间的大小,并不关注内存中存放的是什么数据。
1.2strlen
strlen是库函数,使用它要包含string.h头文件。函数原型如下:
size_t(const char*str);
strlen统计的是所传参数str这个地址开始向后,\0 之前字符串中字符的个数。strlen 函数会⼀直向后找 \0 字符,直到找到为止,所以可能存在越界查找。
这些我们之前都讲过,不在赘述。
1.3sizeof和strlen对比
以上表格总结出来了二者之间的差别,希望大家能熟练掌握。
了解了上面的知识的话,接下来我们先来讲解数组的一些笔试题目
2.数组笔试题讲解
在讲解之前,我们再来回忆一下我们之前所讲的一个知识:
数组名的理解
1. sizeof(数组名),这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩。
2. &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表⽰⾸元素的地址。
不在赘述,我们直接看题。
2.1一维数组
这段代码运行结果是什么呢?
我们一个一个来看:
sizeof(数组名),表示整个数组,计算的是整个数组的大小,故答案为16.
这个也是16吗?不是,我们上面讲的是sizeof(数组名)表示整个数组,前提是括号里面单独跟数组名,但是这个却是a+0,有人会说:这有什么区别呢?根据数学的角度来说这俩完全一样嘛。在数学上,这俩完全一样,
但在这里结果却大不相同:这里没有单独跟数组名,所以此时a表示数组首元素的地址,是个指针,类型是int*类型,a+0还是表示数组首元素的大小,但此时sieof内部是个指针,故sizeof会计算该指针的大小,为4\8.
首先看是否满足单独跟数组名,没有
所以此时a表示数组首元素的地址,是个指针,类型是int*类型,对其解引用得到数组首元素,类型为int,故结果为4\8.
同理,a表示数组首元素地址,是个指针,类型是int*类型,a+1表示数组第二个元素的地址,仍是个指针,所以大小为4\8.
a[1]表示数组第二个元素,类型为int,故答案是4,比较简单。
&a,取出的是整个数组的地址,是个地址,大小仍然为4\8.这里千万不要带着有色眼镜去看,认为整个数组的地址和一个元素的地址不一样!两个都是地址,怎么会不一样呢?只要是地址,大小就是4\8个字节。
这里有两种理解思路:
1.*和&相互抵消掉,所以单独剩下a,表示sizeof(数组名),所以表示整个数组,计算的是整个数组的大小,故答案为16.
2.&a,取出的是整个数组的地址,类型是int(*)[4],是个数组指针,表示指向一个含有 4 个 int 元素的数组的指针。*(&a)对指针解引用,得到整个数组,所以结果是16.
&a,取出了整个数组的地址,&a+1是跳过整个数组后的那个位置的地址,是地址就是4/8个字节,
示意图如下:
a[0]表示数组第一个元素,&a[0]得到第一个元素的地址,是个地址,是地址就是4/8个字节。
至此,我们完成了第一道题目,那么接下来我们来看一下字符数组。
2.2字符数组
题目一:
我们来一 一讲解。
sizeof(数组名),表示整个数组,计算的是整个数组的大小,故结果是6个字节。比较简单。
与上面我们讲的一维数组的第三个一模一样,arr+0是个地址,是地址大小就是4\8个字节
没有满足sizeof(数组名)和&数组名,所以此时arr表示数组首元素的地址,类型为char*,对其解引用访问到数组第一个元素,大小为1个字节
计算数组第二个元素大小,为1个字节。
&arr取出的是整个数组的地址,但是还是个地址,是地址大小就是4\8个字节
&arr+1, 跳过整个数组,指向了数组后边的空间,4/8个字节
第二个元素的地址,是地址就是4/8字节
题目二:
这段代码运行结果又是如何呢?首先看到这段代码,我们就应该看到:arr数组这种初始化方式,数组末尾没有\0,有可能会引发strlen的越界访问。
答案和讲解如下图所示:
题目三:
答案直接给出,和我们上面讲解的题目非常相似,这里就不在赘述。
相对于题目二来说,这个arr数组的初始化方式,会在数组末尾总添加一个\0,题目解析如下图所示:
这里唯一需要注意的是:
&arr得到的是整个数组的地址,类型为char(*)[6],加一跳过整个数组。
接下来,我们来看最后一道题目,有关二维数组的题目。
2.3二维数组
这道题目还是有一定难度的,是我们今天学习的最难的一道题目,我们来一个一个讲解:
sizeof(数组名),表示整个数组,计算的是整个二维数组的大小,结果为48个字节
a[0][0]表示数组第一个元素,大小为4个字节,没什么好讲的。
仔细看这个题目,a[0]表示的是什么呢?a[0]是数组名吗?
我们来回忆一下二维数组:
对于一个二维数组int a[3][4],它的类型是int[3][4],sizeof(数组名)和&数组名表示整个二维数组,而sizeof(a[0])和&a[0]表示的是第0行的整行数组,也就是说a[0]也相当于数组名,只不过它是第0行的数组名。
所以在这里sizeof(a[0])表示的是第一行数组,计算的是数组第一行的大小,结果为16个字节。
此时sizeof没单独跟a[0],a[0]表示数组首元素的地址,a[0]+1表示数组第二个元素的地址,结果为4\8个字节
此时sizeof没单独跟a[0],a[0]表示数组首元素,a[0]+1表示数组第二个元素,在对其解引用得到第二个元素,结果是4个字节。
来看这一组,此时a不是上面所说的两种情况,表示的是二维数组首元素的地址,也就是二维数组第一行的地址(这里要能和a[0]+1作区分),a+1表示第二行的地址,是个地址,结果为4\8个字节;而8对其进行了解引用,得到了数组第二行的元素,故结果为16个字节。
这一组,&a[0]就是&加上第一行的数组名,得到的是第一行的地址,加一跳过一行,得到第二行的地址,是个地址结果为4\8个字节
10对&a[0]+1进行了解引用操作,得到了第二行的元素,故结果为16个字节。
a作为数组名并没有单独放在sizeof内部,a表示数组首元素的地址,是二维数组首元素的地址,也就是第一行的地址,*a就是第一行,计算的就是第一行的大小,16字节
a[3]细心的小伙伴一看,a数组不是只有三行,最多也就是a[2]吗?a[3]是什么鬼。
确实是这样,a[3]不属于数组a,但a[3]无需真实存在
我们上面讲sizeof时就说过sizeof只关心所占内存大小,不关心里面所放数据,sizeof仅仅通过类型的推断就能算出长度a[3]是第四行的数组名,单独放在sizeof内部,计算的是第四行的大小,16个字节。
这与sizeof(int)和sizeof(3+4)结果都是4个字节是一个道理。
至此,我们讲完了数组一些经典的笔试题目,相信大家学完后肯定会对数组有更加深刻的理解。
至于指针的笔试题讲解,我们放到下篇来讲。