指针和数组笔试题解析(最详细解析,没有之一)

前言

指针和数组在许多编程场景中经常结合使用,比如通过指针来访问数组的元素、通过指针来遍历数组等。指针和数组的灵活应用可以帮助我们更好地处理和操作数据,提高程序的性能和效率,指针和数组在C语言中具有重要的地位和作用,它们是程序设计中不可或缺的重要概念。本文将详细解析指针和数组相关笔试题!!

1. 一维数组和指针相关笔试题

题目及解析:

int main()
{
    
    
	int a[] = {
    
     1,2,3,4 };

	printf("%d\n", sizeof(a));	//数组名单独放在sizeof内部,这里a表示整个数组,计算的是整个数组,为16(4*4)个字节
	printf("%d\n", sizeof(a + 0));//a表示首元素的地址,a+0还是表示首元素地址,是地址就是4/8个字节
	printf("%d\n", sizeof(*a));	//a表示首元素地址,*a表示首元素,大小为4个字节
	printf("%d\n", sizeof(a + 1));//a表示首元素地址,arr+1跳过一个整型长度指向第二个元素(2)的地址,是地址大小就是4/8个字节
	printf("%d\n", sizeof(a[1]));//a[1]取出的是第二个元素2,为int类型,大小为4个字节
	printf("%d\n", sizeof(&a));	//&a取出的是整个数组的地址,但只要是地址,大小都是4/8个字节

	printf("%d\n", sizeof(*&a));	
	//解读一:sizeof(*&a) ---> sizeof(a) ---> 同第一个为16字节
	//解读二:由于我们熟知对整型指针进行解引用得到的是整型;对字符指针进行接引用得到的是一个字符
	//		  这里&a表示数组指针,类型为int (*)[4],对它进行解引用操作得到的是一个数组,即*&a表示整个数组,大小为4*4即16个字节

	printf("%d\n", sizeof(&a + 1));
	//&a取出的是整个数组,&a+1跳过整个数组,指向的是第四个元素4的下一个元素的地址
	//但是地址大小就是4/8个字节

	printf("%d\n", sizeof(&a[0]));//&a[0]取出的是第一个元素1的地址,大小为4/8个字节
	printf("%d\n", sizeof(&a[0] + 1));//&a[0]+1表示取出首元素地址后向后移动一个整型字长,指向第二个元素2的地址,为4/8个字节

	return 0;
}

x64环境下运行结果:
在这里插入图片描述

2. 字符数组和指针相关笔试题

2.1 题型一:

题目及解析:

int main()
{
    
    
	char arr[] = {
    
     'a','b','c','d','e','f' };
	
	printf("%d\n", sizeof(arr));//数组名单独放在sizeof内部,这里的arr表示整个数组,计算的是整个数组的大小,单位是字节,总共6个字节
	printf("%d\n", sizeof(arr + 0));//arr表示数组首元素的地址,arr+0还是数组首元素的地址,是地址就是4/8个字节
	printf("%d\n", sizeof(*arr));//arr表示数组首元素的地址,*arr就是首元素,大小1个字节
	printf("%d\n", sizeof(arr[1]));//arr[1]就是第二个元素,大小是1个字节

	printf("%d\n", sizeof(&arr));//&arr是数组的地址,但是数组的地址也是地址,是地址就是4/8

	printf("%d\n", sizeof(&arr + 1));//&arr + 1是跳过整个数组后的地址,是地址就是4/8个字节
	printf("%d\n", sizeof(&arr[0] + 1));//第二个元素的地址,是4/8个字节
	return 0;
}

x64环境下运行结果:
在这里插入图片描述

2.2 题型二:

题目及解析:

int main()
{
    
    
	char arr[] = {
    
     'a','b','c','d','e','f' };
	printf("%d\n", strlen(arr));//因为字符数组arr中没有\0,所以在求字符串长度的时候,会一直往后找,产生的结果就是随机值
	printf("%d\n", strlen(arr + 0));//arr + 0是首元素的地址,和第一个一样,也是随机值

	//printf("%d\n", strlen(*arr));//err, arr是数组首元素的地址,*arr就是数组首元素,就是'a'-97
	//strlen函数参数的部分需要传一个地址,当我们传递的是'a'时,'a'的ascii码值是97,那就是将97作为地址传参
	//strlen就会从97这个地址开始统计字符串长度,这就非法访问内存了
	//printf("%d\n", strlen(arr[1]));//err

	printf("%d\n", strlen(&arr));//&arr是数组的地址,数组的地址和数组首元素的地址,值是一样的
								 //那么传递给strlen函数后,依然是从数组的第一个元素的位置开始往后统计,结果为随机值

	printf("%d\n", strlen(&arr + 1));//&arr+1,跳过整个数组,结果为随机值
	printf("%d\n", strlen(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址,结果为随机值
	return 0;
}

x64环境下运行结果:
在这里插入图片描述

2.3 题型三:

题目及解析:

int main()
{
    
    
	char arr[] = "abcdef";//[a b c d e f \0]
	printf("%d\n", sizeof(arr));//数组中共有7个元素,结果为7

	printf("%d\n", sizeof(arr + 0));//arr + 0是首元素的地址,结果为4/8
	printf("%d\n", sizeof(*arr));//*arr其实就是首元素,1个字节
	//*arr--> *(arr+0) -- arr[0]

	printf("%d\n", sizeof(arr[1]));//arr[1]是第二个元素,1个字节
	printf("%d\n", sizeof(&arr));//&arr是数组的地址,是地址就是4/8个字节
	printf("%d\n", sizeof(&arr + 1));//&arr + 1是跳过一个数组的地址,4/8
	printf("%d\n", sizeof(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址 4/8
	return 0;
}

x64环境下运行结果:
在这里插入图片描述

2.4 题型四:

题目及解析:

int main()
{
    
    
	char arr[] = "abcdef";//[a b c d e f \0]

	printf("%d\n", strlen(arr));//6
	printf("%d\n", strlen(arr + 0));//6

	//printf("%d\n", strlen(*arr));//err,传的是首元素a
	//printf("%d\n", strlen(arr[1]));//err,传的是第二个元素b
	//strlen需要传过去的是指针,如果传字符会造成非法访问内存,报错

	printf("%d\n", strlen(&arr));//6
	printf("%d\n", strlen(&arr + 1));//&arr+1跳过整个数组,导致数组后面\0没有明确位置,导致结果为随机值
	printf("%d\n", strlen(&arr[0] + 1));//从第二个元素开始向后访问,结果为5
	return 0;
}

x64环境下运行结果:
在这里插入图片描述

3. 指针和字符串相关面试题

3.1 题型一:

题目及解析:

int main()
{
    
    
	char* p = "abcdef";
	
	printf("%d\n", sizeof(p));//p是一个指针变量,大小就是4/8个字节
	printf("%d\n", sizeof(p + 1));//p+1是'b'的地址,是地址大小就是4/8个字节
	
	printf("%d\n", sizeof(*p));//*p 就是'a',就是1个字节
	printf("%d\n", sizeof(p[0]));//p[0]--> *(p+0) --> *p ,大小为1个字节

	printf("%d\n", sizeof(&p));//&p -- char**,二级指针也是指针大小为4/8个字节
	printf("%d\n", sizeof(&p + 1));//*p+1本质上还是一个指针,大小为4/8个字节
	printf("%d\n", sizeof(&p[0] + 1));//4/8 , &p[0] + 1得到是'b'的地址 

	return 0;
}

x64环境下运行结果:
在这里插入图片描述

3.2 题型二:

**题目及解析:

//由于原理和上面完全一样,所以在此就不再累赘了
int main()
{
    
    
	char* p = "abcdef";

	printf("%d\n", strlen(p));//6
	printf("%d\n", strlen(p + 1));//5
	//printf("%d\n", strlen(*p));//err
	//printf("%d\n", strlen(p[0]));//err
	printf("%d\n", strlen(&p));//随机值
	printf("%d\n", strlen(&p + 1));//随机值
	printf("%d\n", strlen(&p[0] + 1));//5
	return 0;
}

x64环境下运行结果:

4. 二位数组和指针相关面试题

**题目及解析:

int main()
{
    
    
	int a[3][4] = {
    
     0 };

	printf("%d\n", sizeof(a));//sizeof(数组名)不管是一维数组还是二维数组都是表示整个数组,结果为3*4*4 = 48
	printf("%d\n", sizeof(a[0][0]));//大小为4

	printf("%d\n", sizeof(a[0]));//a[0]是第一行这个一维数组的数组名
	//数组名算是单独放在sizeof内部了,计算的是整个数组的大小,大小是16个字节

	printf("%d\n", sizeof(a[0] + 1));
	//a[0]作为第一行的数组名,没有单独放在sizeo内部,没有&
	//a[0]表示数组首元素的地址,也就是a[0][0]的地址
	//所以a[0]+1是第一行第二个元素的地址,是地址就是4/8个字节
	//
	printf("%d\n", sizeof(*(a[0] + 1)));//4
	//计算的是就是第一行第2个元素的大小

	printf("%d\n", sizeof(a + 1));//4 / 8
	//a是数组首元素的地址,是第一行的地址 int(*)[4]
	//a+1 就是第二行的地址

	printf("%d\n", sizeof(*(a + 1)));//16
	//*(a+1) --> a[1] -> sizeof(*(a+1))->sizeof(a[1]) 计算的是第二行的大小
	//a+1 --> 是第二行的地址,int(*)[4]
	//*(a+1) 访问的第二行的数组

	printf("%d\n", sizeof(&a[0] + 1));//4/8
	//&a[0]是第一行的地址 int(*)[4]
	//&a[0]+1 是第二行的地址 int(*)[4]

	printf("%d\n", sizeof(*(&a[0] + 1)));//16 计算的是第二行的大小

	printf("%d\n", sizeof(*a));//计算的是第一行的大小-16
	//a是数组首元素的地址,就是第一行的地址
	//*a 就是第一行
	//*a --> *(a+0) --> a[0]

	printf("%d\n", sizeof(a[3]));//16
	//sizeof在计算其大小时,其背后原理是sizeof操作符只关心其类型,根据类型来计算大小
	//并不会真正的访问内存,所以在此所谓的数组越界对sizeof计算其大小并没有太大关系
	return 0;
}

x64环境下运行结果:
在这里插入图片描述

5. 总结

1. sizeof(数组名),这里的数组表示的是整个数组,不管是一维数组还是二维数组计算的都是整个数组的大小。
2. &数组名,这里的数组名表示的也是整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名表示的都是首元素的地址。
4. sizeof计算大小时,其工作原理是根据其类型来判断的,并不会真正访问内存来计算大小。所以在计算数组大小过程中,即使出现数组越界,但对sizeof来说没有影响,依然可以计算其大小。

6. 结尾

本篇文章到此就结束了。创作不易,如果对你有帮助记得点赞加收藏哦。感谢您的支持!!

猜你喜欢

转载自blog.csdn.net/Zhenyu_Coder/article/details/131691231