一篇文章让你搞懂指针和数组笔试题(加深对指针的理解)

在这里插入图片描述

指针和数组笔试题解析

下文哦我们直接结合代码进行讲述

一维数组

1

//一维数组
#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));
	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;
}

先给大家复习一下
数组名是数组首元素的地址
1:sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节
2:&数组名,这里的数组名表示整个数组,取出的是整个数组的地址
我们一个一个给大家分析一下
1:4*4=16
2:数组名a是首元素的地址,a+0还是首元素的地址,地址的大小是4/8
3:数组名a是首元素的地址,*a就是首元素,大小就是4个字节
4:数组名a是数组首元素的地址,a+1是第二个元素的地址,地址的大小是4/8
5:第二个元素的大小就是4个字节
6:&a是数组的地址,数组的地址也是地址,是地址就是4/8个字节
7:16个字节
8:&a+1相当于&a跳过了是跳过了整个数组,但是即使跳过了整个数组,&a+1还是地址,所以是4/8个字节
9:&a[0]是首元素的地址,4/8个字节
10:&a[0]是首元素的地址,&a[0]+1就是第二个元素的地址,所以是4/8个字节
在这里插入图片描述

//一维数组
#include<stdio.h>
int main()
{
    
    
	//一维数组
	int a[] = {
    
     1,2,3,4 };
	printf("%d\n", sizeof(a));//16
	printf("%d\n", sizeof(a + 0));//4/8
	printf("%d\n", sizeof(*a));//4
	printf("%d\n", sizeof(a + 1));//4/8
	printf("%d\n", sizeof(a[1]));//4
	printf("%d\n", sizeof(&a));//4/8
	printf("%d\n", sizeof(*&a));//16个字节
	//sizeof(*&a)-->sizeof(a)--16
	//&a-->int(*)[4]
	//*&a
	printf("%d\n", sizeof(&a + 1));//4/8
	printf("%d\n", sizeof(&a[0]));//4/8
	printf("%d\n", sizeof(&a[0] + 1));//4/8
	return 0;
}

字符数组

1

//字符数组
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));

依然还是给大家解释一下
1:数组名单独放在sizeof内部,这里的arr表示整个数组,计算的是整个数组的大小,单位是字节,所以一共6个字节
2:arr表示数组首元素的地址,arr+0还是数组首元素的地址,是地址就是4/8个字节
3:arr表示数组首元素的地址,*arr就是首元素,大小为1个字节
4:arr[1]就是第二个元素,大小为1个字节
5:&arr是数组的地址,数组的地址本质上也是地址,地址的大小为4/8个字节
6:&arr+1是跳过整个数组后的地址,是地址就是4/8个字节
7:第二个元素的地址,4/8个字节
在这里插入图片描述

#include<stdio.h>
int main()
{
    
    
	//字符数组
	char arr[] = {
    
     'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));//6个字节
	printf("%d\n", sizeof(arr + 0));//4/8个字节
	printf("%d\n", sizeof(*arr));//1个字节
	printf("%d\n", sizeof(arr[1]));//1个字节
	printf("%d\n", sizeof(&arr));//4/8个字节
	printf("%d\n", sizeof(&arr + 1));//4/8个字节
	printf("%d\n", sizeof(&arr[0] + 1));//4/8个字节
	return 0;
}

2

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

1:因为字符数组arr中没有\0,所以在求字符串长度的时候,会一直往后找,产生的数值就是随机值
2:arr+0是首元素的地址,和第一个一样也是随机值
3:arr是数组首元素的地址,*arr就是数组首元素,就是’a’—97,这个地址并不是你本身的,所以非法访问
strlen函数参数的部分需要传一个地址,当我们传递的是’a’时,'a’的ASCLL码值是97,那就是将97作为地址传参
strlen就会从97这个地址开始统计字符串长度,这就属于非法访问了
4:error//同理第三行代码

size_t strlen ( const char * str );

5:指针类型转化为srelen参数的类型,站在strlen参数的角度他依然是指向数组首元素的,值传过之后,类型编译器自动转化,所以&arr是数组的地址,数组的地址和数组首元素的地址值是一样的,那么传递给strlen函数后,依然是从数组的第一个元素的位置开始往后统计
6:随机值
7:&arr[0]+1是第二个元素的地址,结果也是随机值
在这里插入图片描述

#include<stdio.h>
#include<string.h>
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));//error//arr是数组首元素的地址,*arr就是数组首元素,就是'a'--97
	//strlen函数参数的部分需要传一个地址,当我们传递的是'a'时,'a'的ASCLL码值就是97,那么就是将97作为地址传参
	//strlen函数会从97这个地址开始统计字符串长度,属于非法访问

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

3

#include<stdio.h>
//#include<string.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));
	return 0;
}

字符串末尾自带\0
1:sizeof只关心你占了多大的空间,所以是7个字节
2:arr+0是首元素的地址
3:*arr其实是首元素,1个字节
4:arr[1]是第二个元素,1个字节
5:&arr是数组的地址,是地址就是4/8个字节
6:&arr+1是跳过一个数组的地址,所以是4/8个字节
7:&arr[0]+1是第二个元素的地址,所以是4/8个字节

#include<stdio.h>
//#include<string.h>
int main()
{
    
    
	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));//7
	printf("%d\n", sizeof(arr + 0));//arr+0是首元素的地址
	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;
}

4

#include<stdio.h>
#include<string.h>
int main()
{
    
    
	char arr[] = "abcdef";
	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;
}

1:在\0之前会找到6个字符,所以为6
2:和第一个相同也为6
3:错误,因为*arr是我们的字符a,所以非法访问
4:错误,和3同理
5:数组的地址也是从字符a开始往后数,所以为6
6:随机值,&arr+1跳过了\0,所以再去找的时候就是随机值
7:跳到字符b处进行访问,所以为5
在这里插入图片描述

#include<stdio.h>
#include<string.h>
int main()
{
    
    
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));//6
	printf("%d\n", strlen(arr + 0));//6
	printf("%d\n", strlen(*arr));//error
	printf("%d\n", strlen(arr[1]));//error
	printf("%d\n", strlen(&arr));//6
	printf("%d\n", strlen(&arr + 1));//随机值
	printf("%d\n", strlen(&arr[0] + 1));//5
	return 0;
}

5

#include<stdio.h>
//#include<string.h>
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));
	return 0;
}

p指向了字符a
1:p是一个指针变量//大小为4/8个字节
2:p+1是’b’的地址,是地址大小就是4/8个字节
3:*p就是首元素’a’,就是一个字节
4:p[0]—>(p+0)—>*p—1个字节
5:&p—4/8个字节
6:&p+1指向指针变量p的末尾,&p用一个二级指针来存储
7:&p[0]+1得到的是’b’的地址
在这里插入图片描述

#include<stdio.h>
//#include<string.h>
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)-->  1个字节
	printf("%d\n", sizeof(&p));//4/8
	printf("%d\n", sizeof(&p + 1));//4/8
	printf("%d\n", sizeof(&p[0] + 1));//4/8//&p[0]+1得到的是'b'的地址
	return 0;
}

6

#include<stdio.h>
#include<string.h>
int main()
{
    
    
	char* p = "abcdef";
	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;
}

字符串本身是可以理解为数组的
字符串是一块连续的空间只不过存放的是字符而已
1:毋庸置疑是6
2:p里面本身存放的是a的地址,加1就是b的地址了,所以是5
3:error—非法访问
4:error—非法访问
5:随机值—对于&p里面的每一个字节是什么我们都不知道,编译器为p分配的地址以及内容是什么我们都不知道,所以什么时候遇到\0我们也不是到,这里会运用到大小端的知识,如果p的地址最后一个字节为十六进制数00也就是\0我们就可以得到确定的数,但是现在我们并不清楚,所以是随机值
6:随机值—和上面的随机值没有关系----因为遇到\0的时机不同等等
7:从’b’的地址开始往后数----5

二维数组

1

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

1:344=48
2:4
3:a[0]是第一行这个一维数组的数组名//数组名算是单独放在sizeof内部了,计算的是整个数组的大小,大小是16个字节
4;a[0]作为第一行的数组名,没有单独放在sizeof内部,没有&,a[0]表示数组首元素的地址,也就是a[0][0]的地址,所以a[0]+1是第一行第二个元素的地址,是地址就是4/8个字节
5:计算的是第一行第二个元素的大小
6:a是数组首元素的地址,是第一行的地址,a+1就是第二行的地址
7:访问的是第二行的数组
8:&a[0]是第一行的地址,&a[0]+1是第二行的地址
9:计算的是第二行的大小—16
10:计算的是第一行的大小—16,a是数组首元素的地址,就是第一行的地址,*a就是第一行,a–>(a+0)–>a[0]
11:16,虽然越界,但是sizeof计算的类型的大小
在这里插入图片描述

//int main()
//{
    
    
//	int a[3][4] = { 0 };
//
//	printf("%d\n", sizeof(a));//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
//	//a[3]--> int [4]
//	//
//	return 0;
//}

总结: 数组名的意义:

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

猜你喜欢

转载自blog.csdn.net/fjj2397194209/article/details/131611851