【指针与数组】笔试题详解!!!

发布于:2025-07-07 ⋅ 阅读:(22) ⋅ 点赞:(0)

C语言学习

指针基础
友情链接:C语言专栏



前言:

经过前面指针基础指针进阶1指针进阶2的学习,咱们对指针已经有了深入的理解,那咱们就来看看指针和数组相关的一些笔试题!


指针和数组笔试题解析

一维数组

看一下下面代码输出都是什么?

#include<stdio.h>
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 + 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;
}

咱们可以自己先试着来分析分析。
结果:请添加图片描述
解释:

#include<stdio.h>
int main()
{
	int a[] = { 1,2,3,4 };
	
	printf("%d\n", sizeof(a));    //数组名遇见sizeof就是数组元素总大小,即为16(字节)

	printf("%d\n", sizeof(a + 0));//看起来与上一个一样,但是,两者还是有区别:
	//单是数组名遇见sizeof的话,就是数组元素总大小;但是这里数组名已经和0进行的算术运算
	//即为首元素地址+0,为首元素地址,故输出为4(32位机器)。

	printf("%d\n", sizeof(*a));   //数组名为首元素地址,*解引用操作后为4(int型数据),输出为4

	printf("%d\n", sizeof(a + 1));//这个和第二个有点像,首元素地址+1;为第二个元素地址,故大小为4;

	printf("%d\n", sizeof(a[1])); //第二个元素大小,即为4;

	printf("%d\n", sizeof(*(a + 1)));//a + 1数组第二个元素的地址;*(a + 1)数组第二个元素;
	//那看起来与a[1]的意思是一样的,其实,a[1]与*(a + 1)是等效的,a[1]是*(a + 1)的简写,
	// 故sizeof(*(a + 1))也为4;

	printf("%d\n", sizeof(&a));   //&a取出数组的地址,地址即为4(32位);

	printf("%d\n", sizeof(*&a));  //*&抵消,和第一个一样,输出为16;
	//或者这样思考:&a取出数组的地址,*&a解引用找到数组,sizeof(*&a)计算数组大小;即为16;

	printf("%d\n", sizeof(&a + 1));//&a取出数组地址,&a + 1地址跳过这个数组(对于这个数组跳16个字节)
	//但它还是地址,即sizeof(&a + 1)为4(32位);

	printf("%d\n", sizeof(&a[0])); //a[0]为数组首元素,&a[0]首元素地址,sizeof(&a[0])即为地址大小,4(32位)

	printf("%d\n", sizeof(&a[0] + 1));//&a[0]首元素地址,&a[0] + 1首元素地址+1,还是地址,即大小为4(32位机器)

	return 0;
}
//主要体会什么叫数组的地址,弄清楚它与首元素地址的区别;

字符数组1

看一下下面代码输出都是什么?

#include<stdio.h>
int main()
{
	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));
	return 0;
}

输出:
在这里插入图片描述
解释:


int main()
{
	char arr[] = { 'a','b','c','d','e','f' };

	printf("%d\n", sizeof(arr));	//数组名遇见sizeof就为整个数组大小,故为6
	
	printf("%d\n", sizeof(arr + 0));//同一维数组,数组名在进行算术运算的时候为首元素地址,
	//地址为4(32位机器)

	printf("%d\n", sizeof(*arr));	//*arr首元素地址*解引用,即为首元素,为1字节

	printf("%d\n", sizeof(arr[1])); //数组第二个元素,大小为1;

	printf("%d\n", sizeof(&arr));   //数组地址,为4(32位机器)

	printf("%d\n", sizeof(&arr + 1));//数组地址+1,还是地址,为4(32位机器)

	printf("%d\n", sizeof(&arr[0] + 1));//首元素的地址+1,还是地址,为4(32位机器)

	return 0;
}

字符数组2

看一下下面代码输出都是什么?

#include<stdio.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	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));
	return 0;
}

介于这两串代码会出现访存错误(不属于你的程序),无法输出,咱们就看可以输出的

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

输出:
在这里插入图片描述

解释:

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	
	//对strlen函数简介:
	// 返回类型为字符串大小;
	// 参数为字符串地址
	// 是用来计算字符串大小的函数,遇到'\0'停止,

	printf("%d\n", strlen(arr));      //对于数组arr没有'\0',咱们不知道从首元素地址起哪里有'\0',
	//故不知道输出为多少,

	printf("%d\n", strlen(arr + 0));  //解释同上;

	printf("%d\n", strlen(*arr));	  //*arr对首元素地址*解引用,即为首元素,
	//它会把'a'(97)当作内存地址去访问,会有意想不到的错误

	printf("%d\n", strlen(arr[1]));   //解释同上;

	printf("%d\n", strlen(&arr));     //&arr为数组地址,虽然实参类型与形参类型不同,
	//但是形参会将实参的类型转化为与自己相同的类型后再在接受,即隐式类型转化;
	//故输出与strlen(arr)相同

	printf("%d\n", strlen(&arr + 1));  //&arr + 1跳过整个数组之后的地址,之后道理同上虽然传过去的是数组地址,
	//但是会发生隐式类型转化,因为跳过了6个元素,故它的输出比上一个少6;

	printf("%d\n", strlen(&arr[0] + 1));//首元素地址+1,故输出比strlen(arr)少1

	return 0;
}

字符数组3

看一下下面代码输出都是什么?

#include<stdio.h>
int main()
{
	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));
	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));
	return 0;
}

与字符数组2中类似的就不再解释了:

int main()
{
	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));	//数组名遇见sizeof就为整个数组大小,但是咱们这里要注意
	//字符串后面还有一个隐藏的\0呢,所以应该为7,

	printf("%d\n", sizeof(arr + 0));//4
	printf("%d\n", sizeof(*arr));   //1
	printf("%d\n", sizeof(arr[1])); //1
	printf("%d\n", sizeof(&arr));   //4
	printf("%d\n", sizeof(&arr + 1));//4
	printf("%d\n", sizeof(&arr[0] + 1));//4
	printf("%d\n", strlen(arr));   //注意:
	//strlen遇见\0就停止,即为6

	printf("%d\n", strlen(arr + 0));//6
	printf("%d\n", strlen(*arr));//访问内存失败
	printf("%d\n", strlen(arr[1]));//访问内存失败
	printf("%d\n", strlen(&arr));//6
	printf("%d\n", strlen(&arr + 1));//随机,直到遇到\0

	printf("%d\n", strlen(&arr[0] + 1));//5
	return 0;
}

字符数组4

int main()
{
	char* p = "abcdef";
	printf("%d\n", sizeof(p));
	printf("%d\n", sizeof(p + 1));
	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[0] + 1));
	printf("%d\n", strlen(p));
	printf("%d\n", strlen(p + 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[0] + 1));
	return 0;
}

首先,咱们先对char* p = "abcdef"解释一下:

p作为一个字符指针,它需要接收字符的地址
所以这个代码的意思是:将字符串的第一个元素的地址给p

解释:

int main()
{
	char* p = "abcdef";
	printf("%d\n", sizeof(p));    //p首元素地址,大小为4(32位机器)

	printf("%d\n", sizeof(p + 1));//p + 1第二个元素地址,大小为4(32位机器)

	printf("%d\n", sizeof(*p));   //*p首元素地址解引用即为首元素,大小为1

	printf("%d\n", sizeof(p[0])); //p[0]前面说过,相当于*p+0;即与前一个一样,为1;

	printf("%d\n", sizeof(&p));   //p为首元素地址,即字符指针,&p则为二级指针,二级指针也是指针呀,大小为4(32位机器)

	printf("%d\n", sizeof(&p + 1));//&p二级指针,&p + 1二级指针跳过一个一级指针(32位机器为4字节),但是它还是地址
	//所以为4(32位机器)

	printf("%d\n", sizeof(&p[0] + 1));//p[0]即为a,&p[0]取出首元素地址,&p[0] + 1首元素地址+1,第二个元素地址,大小为4(32位机器)
	
	printf("%d\n", strlen(p));     //传入首元素地址,即求的是字符串长度,为6;

	printf("%d\n", strlen(p + 1)); //传入第二个元素地址,即求的是从第二个元素起的字符串长度,为5;

	//printf("%d\n", strlen(*p));    //传入首元素,等效于strlen('a')->strlen(98);会导致内存访问错误;

	//printf("%d\n", strlen(p[0]));  //同上,内存访问错误

	printf("%d\n", strlen(&p));    //&p,二级指针,结果未知

	printf("%d\n", strlen(&p + 1));//同上,结果未知,且两者无联系;

	printf("%d\n", strlen(&p[0] + 1));//&p[0]为首元素地址,&p[0] + 1为第二个元素的地址,
	//即求的是从第二个元素起的字符串长度,为5

	return 0;
}

输出(内存访问错误无输出):
在这里插入图片描述

二维数组

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

输出
在这里插入图片描述
解析:

int main()
{
	int a[3][4] = { 0 };//未完全初始化,默认其他为0;

	printf("%d\n", sizeof(a));        //同上,整个数组大小,即为48;

	printf("%d\n", sizeof(a[0][0]));  //第0行第0列元素大小,即为4(int);

	printf("%d\n", sizeof(a[0]));	  //a[0]代表第0行元素,即一维数组,故大小为4*4(int),为16;

	printf("%d\n", sizeof(a[0] + 1)); //a[0]进行算数运算时,和一维数组一样,代表第0行数组(一维数组)的首元素(第0个元素)地址,
	//a[0] + 1即为第0行第一个元素地址,故大小为4(32位机器);

	printf("%d\n", sizeof(*(a[0] + 1)));//a[0] + 1为第0行第一个元素地址,*解引用即为第0行第一个元素,故大小为4;

	printf("%d\n", sizeof(a + 1));		//二维数组数组名为第0行地址(一维数组地址),数组名a + 1即为第1行地址(一维数组地址),
	//地址大小为4(32位机器)

	printf("%d\n", sizeof(*(a + 1)));   //a + 1为第1行地址,*解引用即为第1行元素,故大小为16;

	printf("%d\n", sizeof(&a[0] + 1));  //a[0]表示第0行(即一维数组),&a[0]表示第0行地址,&a[0] + 1即为第1行地址,大小为4(32位机器);

	printf("%d\n", sizeof(*(&a[0] + 1)));//&a[0] + 1为第1行地址,*解引用则为第1行元素,大小为16;

	printf("%d\n", sizeof(*a));			 //a为首行元素地址(一维数组地址),*解引用即为首行元素,大小为16;

	printf("%d\n", sizeof(a[3]));        //很明显,已经越界了,但是sizeof不计算表达式,仅分析类型,因此即使越界也不会报错。
	//所以咱们还是来看看,a[3]->*(a+3),同上,还是16;

	return 0;
}

所以咱们这里可以再进行一次总结

数组名的意义:

  1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
  2. & 数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
  3. 除此之外所有的数组名都表示首元素的地址。

附录

上文链接

【指针】进阶2

专栏

C语言专栏


网站公告

今日签到

点亮在社区的每一天
去签到