指针笔试题解析(非编程题)上篇

目录

题目组一:一维整型数组

题目组二:一维字符型型数组(sizeof)

题目组三:一维字符型数组(strlen)

题目组四:字符串(sizeof)

题目组五:字符串(strlen)

题目组六:指针指向字符串

 题目组七:整型二维数组(sizeof)


引言

指针的相关内容我在前面已经铺垫了很多了,从初阶到进阶,有兴趣的可以去看一下我之前的博客:认识初阶指针_SAKURAjinx的博客-CSDN博客     全站最细的C语言指针进阶_SAKURAjinx的博客-CSDN博客

今天我们来看一下指针笔试相关的面试题(非编程类)。

在进行解析之前我们再简单梳理一下相关的知识:

一、sizeof是计算变量和类型的大小,它是操作符不是函数;strlen是计算字符串的长度,遇到 ' \0 ' 结束,它是函数且只能用于字符串的计算。

二、数组名代表数组首元素地址,但有两个例外:

1、sizeof(数组名),这里的数组名代表的就是整个数组,sizeof计算整个数组的大小。

2、&数组名,这里也是代表整个数组

题目组一:一维整型数组

int main()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a+0));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a+1));
	printf("%d\n", sizeof(a[1]));
	printf("%d\n", sizeof(&a));
	printf("%d\n", sizeof(*&a));
	printf("%d\n", sizeof(&a+1));
	printf("%d\n", sizeof(&a[0]));
	printf("%d\n", sizeof(&a[0]+1));

	return 0;
}

第一个:sizeof(a),如上文所述,sizeof(数组名)计算的是整个数组的大小,所以是4*4=16

第二个:sizeof(a+0),数组名不是单独放在sizeof里面,所以代表的是首元素地址,地址也就是指针,只要是指针,不管什么类型在32位平台下就是4,在64位平台下就是8。 ( 以下皆默认32位平台下)

第三个:sizeof(*a), arr是首元素地址,*解引用取出数组a的地址,拿到的就是第0个元素,也就是a[0],数组是整型数组,每个元素是整型int,所以是4.

第四个:sizeof(a+1),首元素地址+1,跳过一个元素,即第1个元素的地址,a[1]的地址,为4。

第五个:sizeof(a[1]), 是第一个元素,类型为int,大小为4.

第六个:sizeof(&a),之前说&a是整个数组的地址,那是不是16呢?答案不是16,是4,虽然取出的是整个数组的地址,但是只要是地址,32位平台下就是4.

第七个:sizeof(*&a),先取出整个数组的地址,再对其解引用,就是整个数组,所以答案是16.

也可以这么理解:&后再*,这两个就抵消了,所以直接等于sizeof(a)。

第八个:sizeof(&a+1),取出整个数组的地址后+1,跳过整个数组长度,也就是4个整型元素,

指向的是a[4]的地址,所以大小是4.

第九个:sizeof(&a[0]),第0个元素取地址,取出的是地址,大小是4.

第十个:sizeof(&a[0]+1),即第1个元素的地址,也就是&a[1],大小是4.

整型一维数组相对简单,下面来看字符数组。

题目组二:一维字符型型数组(sizeof)

	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr + 0));
	printf("%d\n", sizeof(*arr));
	printf("%d\n", sizeof(arr[1]));
	printf("%d\n", sizeof(&arr));
	printf("%d\n", sizeof(&arr + 1));
	printf("%d\n", sizeof(&arr[0] + 1));

第一个:sizeof(arr), 计算整个数组的大小,字符数组一个元素大小是1,所以结果是6.

第二个:sizeof(arr+0),首元素地址,不管是char还是int,大小都是4.

第三个:sizeof(*arr),即arr[0],大小是1.

第四个:sizeof(arr[1]),大小是1。

第五个:sizeof(&arr),取出整个数组的地址,大小是4.

第六个:sizeof(&arr+1),跳过的整个数组,指向arr[6]的地址,大小是4.

第七个:sizeof(&arr[0]+1),将数组第0个元素地址取出,往后跳一位,即&arr[1],大小是4.

题目组三:一维字符型数组(strlen)

	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));

注意strlen是遇到 ' \0 ' 后结束。

第一个:这里不是在sizeof里面,所以arr代表数组首元素,strlen计算从首元素开始数起,字符串的长度,但是不知道哪里碰到 ' \0 ',所以值是未知的随机值。

第二个:和第一个一样,是数组首元素地址,所以也是随机值,且和第一个随机值一样大。

第三个:对arr解引用,即arr[0],注意:这里arr[0]和上面两个不一样,上面是从arr[0]的地址处往后数,碰到 '\0'结束,这里只是一个元素,一个元素不能用strlen计算,因为strlen是计算字符串的大小,所以这里会报错。

第四个:和上面一个如出一辙,也会报错。也可以这么理解,给的arr[1]实际值是98,也就是给strlen的地址是'98'处的,这是个野指针,不知道指向哪里,所以不能这么用,会报错。

第五个:取出整个数组的地址,也是从首元素地址处开始往后数,所以也是随机值。或者这么理解:&arr的类型是char(*)[ ]  虽然类型和sizeof(arr)的char 不一样,但是传给strlen的时候都被转化成strlen的默认参数类型const char*了,所以是一样的。

第六个:跳过了一个数组大小,指向了arr[6]处的地址,所以是随机值,比第一个随机值小6.

第七个:从第1个元素的地址,所以是随机值,且比第一个随机值小1.

题目组四:字符串(sizeof)

	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr + 0));
	printf("%d\n", sizeof(*arr));
	printf("%d\n", sizeof(arr[1]));
	printf("%d\n", sizeof(&arr));
	printf("%d\n", sizeof(&arr + 1));
	printf("%d\n", sizeof(&arr[0] + 1));

换汤不换药,我们来看一下:

第一个:字符串末尾默认有个 '\0',所以其实存了7个字符,sizeof(arr)代表整个数组大小,也就是7.

第二个:首元素地址大小为4.

第三个:第0个元素arr[0],大小是1.

第四个:第一个元素大小是1.

第五个:大小是4.

第六个:跳过一整个数组,指向arr[7]的地址,大小是4.

第七个:第一个元素的地址,大小是4.

题目组五:字符串(strlen)

	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));

第一个:这里有 ' \0 '了,从首元素地址开始数,字符串长度为6.

第二个:和上面一样,6.

第三个:会报错,题目三讲了。

第四个:报错。

第五个:和题目三中一样,值为6.

第六个:跳过字符串(包括 ' \0 '),所以是随机值。

第七个:arr[1]处的地址,长度是6-1=5.

题目组六:指针指向字符串

	char* p = "abcdef";
	printf("%d\n", sizeof(p));
	printf("%d\n", sizeof(p + 0));
	printf("%d\n", sizeof(*p));
	printf("%d\n", sizeof(p[1]));
	printf("%d\n", sizeof(&p));
	printf("%d\n", sizeof(&p + 1));
	printf("%d\n", sizeof(&p[0] + 1));

	printf("%d\n", strlen(p));
	printf("%d\n", strlen(p + 0));
	printf("%d\n", strlen(*p));
	printf("%d\n", strlen(p[1]));
	printf("%d\n", strlen(&p));
	printf("%d\n", strlen(&p + 1));
	printf("%d\n", strlen(&p[0] + 1));

这里不是将"abcdef"传给指针变量p,而是将字符串的首元素地址传给p。

sizeof :

第一个:指针变量p是字符串首元素地址,sizeof(p)就是4.

第二个:和第一个一样,首元素地址,大小为4.

第三个:对p解引用,拿到的是第0个元素,' a ' ,大小是1。

第四个:即字符串第1个元素' b ',大小是1.

第五个:对地址取地址,可以理解为二级指针,大小是4.

第六个:取p的地址,+1跳过p,还是个地址,大小是4.

 第七个:p[0]是第0个字符,&p[0]是第0个字符的地址,+1就是第一个字符的地址,大小是4.

strlen:

第一个:从字符串首元素地址开始数,字符串长度为6.

第二个:和第一个一样,字符串长度为6.

第三个:第0个元素,即'a',报错。

第四个:第一个元素,'b',报错。

第五个:取地址的地址,拿到的是变量p的地址,变量p里存的是字符串的地址,这里拿到的新的地址和字符串就没有关系了,是新的内存空间,完全不知道什么时候会碰到 '\0' ,所以字符串长度是随机值。可以借助上图理解

第六个:跳过p的地址空间,即从新的地址空间往后一位开始数碰到 '\0'为止,也是随机值。但是注意,这里的随机值和上面一个没有关系,不是&p+1就比&p大6,因为我们不知道&p+1什么时候碰到 '\0'

 有可能第一个就碰到了,也有可能后面才碰到,这片新空间是未知的。

第七个:第一个元素的地址,字符串长度是6-1=5.

 题目组七:整型二维数组(sizeof)

 二维数组要相对复杂一些,但本质还是一样的。

第一个:sizeof(数组名),整个数组的大小,4*12=48.

第二个:首元素的大小,为4.

第三个:数组第0行的大小,就是4*4=16,或者可以站在一维数组的角度理解:

二维数组第0行可以这么表示:a[0][i], i : 0~3 ,同样的,第1行,第2行也可以这么表示,

a[1][i],a[2][i] ,所以a[0]就是二维数组第0行的数组名,数组名单独放在sizeof里计算的是数组的大小,就是a[0]数组的大小,4*4=16.

第四个:a[0]+1不是数组名单独放在sizeof内部,代表的是数组首元素的地址,也就是&a[0][0],+1就是第0行第1个元素的地址,大小是4.

第五个:对上面的地址解引用,就是第0行第1个元素的大小,为4.

第六个:a是二维数组的数组名,不是单独放在sizeof内部,所以是第0行的地址,+1表示第1行的地址,大小为4。

第七个:对第1行的地址解引用,拿到的是整个第1行,大小是4*4=16 。换种理解方式:*(a+1)可以写成a[1],和上面第三个的理解方式一样,计算的是第1行的大小。

第八个:a[0]可以理解成一维数组的数组名,&a[0]就是第0行的地址,+1就是第1行的地址,大小是4,和sizeof(a+1)表示的一样,写法不同,注意要和a[0]+1区别开,容易搞混。

第九个:对上面的接引用,和第七个一样,表示第1行的大小,结果是16.

第十个:对二维数组数组名解引用,也就是对二维数组第0行解引用,拿到的是第0行,计算大小为16.

第十一个:有人可能会说超出数组的范围越界了,其实这里sizeof没有访问第3行的元素,他只是拿了第3行的地址,判断了一下它的类型。sizeof不管你里面是什么,他只关注你的类型, 像       int a=10;  sizeof(int)和sizeof(a)都可以计算,是因为sizeof会自己判断类型,所以很容易判断这里a[3]和上面是一样的类型的,所以得出和a[0]一样的结论是16.

指针的非编程类题目就讲到这里,下一次我们来看笔试的编程题吧!

  • 2
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:游动-白 设计师:我叫白小胖 返回首页
评论

打赏作者

SAKURAjinx

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值