指针与数组(笔试题详解析)

✨✨✨学习的道路很枯燥,希望我们能并肩走下来!

编程真是一件很奇妙的东西。你只是浅尝辄止,那么只会觉得枯燥乏味,像对待任务似的应付它。但你如果深入探索,就会发现其中的奇妙,了解许多所不知道的原理。知识的力量让你沉醉,甘愿深陷其中并发现宝藏。


前言

本篇对于进一步了解指针和数组有更多的帮助,对指针,数组的练习进行总结,如有错误,请在评论区指正,让我们一起交流,共同进步!


本文开始

1.一维数组

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

题目:
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));

代码详解:

int main()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));//16
	//a是数组名 单独 放在sizeof()中代表整个数组,是一种特殊情况
	printf("%d\n", sizeof(a + 0));//4/8
	//是地址,首元素地址,数组名a 不是单独放在sizeof内部,也没有&
	//地址大小取决于平台,32位平台4个自己,64位平台8个字节(是地址大小就是4或8个字节)
	printf("%d\n", sizeof(*a));//4
	//a是首元素地址,*a是首元素大小
	printf("%d\n", sizeof(a + 1));//4/8
	//a非单独放置,a是首元素地址,a+1(跳过一个int)是第二个元素的地址
	printf("%d\n", sizeof(a[1]));//4/8
	//a[1]是数组的第二个元素

	printf("%d\n", sizeof(&a));//4/8
	//&a取出的数组的地址,数组的地址一样是地址,地址就是4/8个字节
	//a - int* - 整形指针
	//&a - int(*)[4] - 数组指针
	//两者地址值一样,但意义不同,+1走的不同

	printf("%d\n", sizeof(*&a));//16
	//&a是数组的地址,是数组指针类型,*&a是数组指针的解引用,访问一个数组的大小
	//sizeof(*&a) <==> sizeof(a)

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

2.字符数组

2.1字符数组无\0情况

sizeof 是计算对象或者类型创建的对象所占空间的大小
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));

①字符数组 (数组元素为单字符 ‘x’)sizeof 求字节数

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));//6
	//arr是数组名,并且是单独放在sizeof内部,计算的是数组总大小 - 6
	printf("%d\n", sizeof(arr + 0));//4/8
	//arr非单独放在sizeof内部,arr是首元素的地址 - 4/8
	printf("%d\n", sizeof(*arr));//1
	//arr非单独放在sizeof内部,arr是首元素地址,*arr是首元素,计算的是首元素大小 - 1
	printf("%d\n", sizeof(arr[1]));//1
	//arr[1]是数组的第二个元素,计算的是第二个元素的大小 - 1
	printf("%d\n", sizeof(&arr));//4/8
	//&arr 取出的是数组的地址,计算的是数组的地址 - 4/8
	printf("%d\n", sizeof(&arr + 1));//4/8
	//&arr数组地址,&arr + 1 跳过整个数组,指向'f'的后面,但是本质是地址
	//没有越界,只是找到地址,但没有取值
	printf("%d\n", sizeof(&arr[0] + 1));//4/8
	//&arr[0]是'a'的地址,&arr[0]+1是'b'的地址,地址=》4/8
	return 0;
}

②字符数组 (数组元素为单字符 ‘x’) strlen 求字符串长度

  1. strlen:求字符串长度,计算字符串中\0之前的字符个数(没有找到\0会一直往后找)
  2. strlen工作是找地址

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));

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", strlen(arr));//随机值
	//arr是数组名,非sizeof内部,没有&,arr为首元素地址
	//strlen得到arr,从arr数组首元素的地方开始计算字符串的长度,
	//直到找到\0,但是数组中没有\0,arr内存的后面是否有\0,出现的位置是随机的(我们不能确定)

	printf("%d\n", strlen(arr + 0));//随机值
	//arr是数组首元素的地址,arr+0还是首元素地址,原因同上一样产生随机值
	printf("%d\n", strlen(*arr));//err
	//*arr取的是首元素 'a' 
	//'a'ASCII码值是 97 ,把97当成地址,我们不知道97地址中存放的是什么会非法访问地址产生错误
	printf("%d\n", strlen(arr[1]));//err
	//arr[1]是第二个元素'b' - 98 - 原因同上一个非法访问地址产生错误
	printf("%d\n", strlen(&arr));//随机值
	//&arr是数组地址,也指向数组起始位置
	printf("%d\n", strlen(&arr + 1));//随机值,从'f'+ 1地址开始查找
	printf("%d\n", strlen(&arr[0] + 1));//随机值,从'b'地址开始查找
	return 0;
}

2.2字符数组有\0情况

字符数组 (数组元素为字符串"xxx") 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));

int main()
{
	char arr[] = "abcdef";
	//字符串中含有\0,注意:\0也属于字符
	printf("%d\n", sizeof(arr));//7(计算6是忘记\0字符了,一定要注意)
	//arr是数组名,单独放在sizeof中,求的是数组的总字节数
	printf("%d\n", sizeof(arr + 0));// 4/8
	//arr+0代表数组首元素地址
	printf("%d\n", sizeof(*arr));//1
	//取的是数组首元素'a',一个字符是1个字节
	printf("%d\n", sizeof(arr[1]));//1
	//arr[1]是数组第二个元素'b'
	printf("%d\n", sizeof(&arr));// 4/8
	//&arr是整个数组的地址
	printf("%d\n", sizeof(&arr + 1));// 4/8
	//&arr+1是跳过整个数组,也是地址
	printf("%d\n", sizeof(&arr[0] + 1));// 4/8
	//&arr[0]是数组首元素地址,&arr[0]+1是第二个元素的地址
	return 0;
}

字符数组 (数组元素为字符串"xxx") strlen求字符串长度

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));

int main()
{
	char arr[] = "abcdefg";
	printf("%d\n", strlen(arr));//7
	//arr数组地址,一样指向数组首元素地址,从首元素地址开始
	printf("%d\n", strlen(arr + 0));//7
	//arr+0也是数组首元素地址
	printf("%d\n", strlen(*arr));//err
	//*arr取得是数组首元素'a'
	printf("%d\n", strlen(arr[1]));//err
	//arr[1]取得是数组元素'b'
	printf("%d\n", strlen(&arr));//7
	//&arr是数组地址,一样指向数组首元素地址,从首元素地址开始
	printf("%d\n", strlen(&arr + 1));//随机值
	printf("%d\n", strlen(&arr[0] + 1));//6
	return 0;
}

2.3 字符指针存放字符串

注意:
①p是指针变量,存放的是字符串的地址(a的地址)
②从&p往后数是未知的,结果是随机值
③字符串开辟一块空间存值,指针变量p开辟一块空间存字符串地址

字符指针指向的字符串可能不好理解,可以与下面图结合,容易理解(例如:&p,&p+1的理解)

图解:在这里插入图片描述

char *p = “abcdef”;
printf(“%d\n”, sizeof§);
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§);
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));

int main()
{
	const char* p = "abcdef";
	printf("%d\n", sizeof(p));// 4/8
	//p是指针存放a的地址
	printf("%d\n", sizeof(p + 1));// 4/8
	//p+1是指向'b'的指针(地址)
	printf("%d\n", sizeof(*p));// 1
	//*p是首元素'a'
	printf("%d\n", sizeof(p[0]));// 1
	//p[0] => *(p+0)是首元素'a'
	printf("%d\n", sizeof(&p));// 4/8
	//&p是字符串的地址
	printf("%d\n", sizeof(&p + 1));// 4/8
	//&p+1跳过一个p,4个字节(x86环境下)
	printf("%d\n", sizeof(&p[0] + 1));// 4/8
	//&p[0]+1是'b'的地址

	//a b c d e f \0
	printf("%d\n", strlen(p));//6
	//p指向'a'的地址
	printf("%d\n", strlen(p + 1));//5
	//p+1指向'b'的地址
	printf("%d\n", strlen(*p));//err
	//*p是'a'的值
	printf("%d\n", strlen(p[0]));//err
	//p[0]是'a'的值
	printf("%d\n", strlen(&p));//随机值
	//指针p存放的是字符串地址,从&p开始向后找不知道会有什么值,未知
	printf("%d\n", strlen(&p + 1));//随机值 
	//&p+1跳过一个p的地址,p的地址后面是什么也未知
	//p中的4个字节所存放的值,也不能保证没有\0
	printf("%d\n", strlen(&p[0] + 1));// 5

	return 0;
}

3.二维数组

二维数组名

  1. a[0][ ], a[1][ ], a[2][ ]代表每一行的地址
    a[0]相当与数组名,与一维数组a一样
  2. 任何一个表达式都有2个属性
    3+5 ,1个值属性:8 ,1个类型属性:int

sizeof:内部不进行运算
结果最终是(num)short类型=》2

int main()
{
	
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//48
	//a是二维数组的数组名,数组名单独放到sizeof中,计算的数组的总大小,单位字节
	printf("%d\n", sizeof(a[0][0]));//4
	//a[0][0]是首元素- 一个整形
	printf("%d\n", sizeof(a[0]));//16
	//把二维数组的每一行看作一维数组的时候,a[0]是第一行的数组名,
	//第一行的数组名单独放的sizeof中,计算的是第一行的总大小
	printf("%d\n", sizeof(a[0] + 1));// 4/8  
	//a[0]虽是第一行数组名,但没有单独放到sizeof中
	//a[0]作为第一行的数组名并非表示第一行这个数组,a[0]就是第一行首元素地址,a[0] =>&a[0][0]-int*
	//a[0]+1,跳过一个int,是a[0][1]的地址
	printf("%d\n", sizeof(*(a[0] + 1)));// 4
	//a[0]+1是第二个元素的地址,*(a[0]+1)是第二个元素 int

	printf("%d\n", sizeof(a + 1)); // 4/8
	//a没有单独放到sizeof中,没有&,所有a是首元素的地址
	// 可以将二维数组看作一个一维数组,二维数组第一个元素就是二维数组的第一行
	//二维数组中 数组名 代表第一行的地址
	//a+1就是第二行的地址
	printf("%d\n", sizeof(*(a + 1)));// 16
	//a+1是第二行的地址,对数组指针解引用,表示第二行的大小
	//*(a+1) => a[1] 

	printf("%d\n", sizeof(&a[0] + 1));// 4/8
	//&a[0]是第一行的地址,&a[0]+1是地二行的地址
	printf("%d\n", sizeof(*(&a[0] + 1)));// 16
	//对第二行解引用就拿到第二行
	//*(&a[0]+1) => a[1]
	printf("%d\n", sizeof(*a));// 16
	//a是首元素的地址,就是第一行的地址 -&a[0]
	//*a - 拿到的就是第一行
	//*(a+0) ->a[0]
	printf("%d\n", sizeof(a[3]));// 16
	//能够分析处a[3]的类型是:int [4]
	//a[3]是二维数组的第4行,虽然没有第四行,但是类型能够确定,大小就是确定的
	//大小就是一行的大小
	//任何一个表达式都有2个属性
	//3+5 ,1个值属性:8 ,1个类型属性:int
	return 0;
}

小结:

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

总结

✨✨✨各位读友,本篇分享到内容是否更好的让你理解了指针,数组,如果对你有帮助给个👍赞鼓励一下吧!!
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值