c语言经典指针和数组笔试题解析

前面我们已经学习了数组,指针初阶和进阶。学了上述知识还没有练习多少题目,接下来就来看看c语言经典指针和数组笔试题解析

一维数组

#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;
}

我们在进行题目练习之前回顾一下基础知识
sizeof()计算的是数据所占空间的大小单位是字节。
数组名代表的是数组首元素的地址,但是有两种情况除外:

  • sizeof(数组名) 计算的是整个数组的大小,注意是只有数组名,有其他操作就不是整个数组的大小了。
  • &数组名,取出的是整个数组的地址,+1,-1跳过的是整个数组。

地址的大小是4/8,与电脑有关。

题目解析

#include<stdio.h>
int main()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));//16
	//sizeof(数组名),计算的是整个数组的大小,
	//所以输出值为4*4=16

	printf("%d\n", sizeof(a + 0));// 4/8
	//sizeof()内部a并不是单独存在的,也没有&
	//所以数组名代表的是数组首元素的地址
	printf("%d\n", sizeof(*a));//4
	//*a中a是数组首元素的地址,*a找到的就是数组首元素
	//首元素是整形,大小是4字节

	printf("%d\n", sizeof(a + 1));//4/8
	//a是数组首元素的地址,a+1是数组第二个元素的地址。
	//地址的大小是4/8
	printf("%d\n", sizeof(a[1]));//4
	//a[1]数组第二个元素,大小4字节。

	printf("%d\n", sizeof(&a));
	//&a是整个数组的地址,只要是地址大小为4/8

	printf("%d\n", sizeof(*&a));//16
	//有两种理解方式
	//1.&a<-->int (*)[4]
	// &a取出的是数组名的地址,类型是int (*)[4],是数组指针
	// 数组指针指向的是数组,*&a-->a
	//
	//2.&和*抵消了,*&a-->a
	
	printf("%d\n", sizeof(&a + 1));// 4/8
	//&a取出的是数组的地址,&a<-->int (*)[4]
	//&a+1 是从数组a的地址向后跳过了一个(4个整形元素)数组的大小。
	//&a+1还是地址,是地址就是4/8字节

	printf("%d\n", sizeof(&a[0]));//4/8
	//a[0]数组首元素,&a[0]数组首元素的地址
	
	printf("%d\n", sizeof(&a[0] + 1));// 4/8
	//&a[0]+1,数组首元素地址+1-->数组第二个元素地址。

	return 0;
}

字符数组

需要补充的知识,strlen是函数,头文件<string.h>,是专门获取字符串长度的函数,字符串的结束标志是’\0’,字符数组什么时候出现‘\0’就是strlen函数获取字符串长度的关键。

第一组–>字符数组

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

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

代码解析

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));//6
	//sizeof(数组名),数组所占空间大小,1*6=6byte
	printf("%d\n", sizeof(arr + 0));// 4/8
	//arr+0,数组名未单独出现在sizeof内,数组名代表数组首元素地址
	//arr+0数组首元素地址
	printf("%d\n", sizeof(*arr));// 1
	//*arr,对数组首元素地址进行解引用,数组首元素。
	//数组首元素是字符型,大小为1byte
	printf("%d\n", sizeof(arr[1]));// 1
	//数组首元素大小1byte
	printf("%d\n", sizeof(&arr));// 4/8
	//&arr,取出整个数组的地址,它是地址
	//是地址大小为4/8
	printf("%d\n", sizeof(&arr + 1));//4/8
	//&arr + 1是数组后的地址。
	printf("%d\n", sizeof(&arr[0] + 1));//4/8
	//&arr[0] + 1是数组第二个元素的地址

	printf("%d\n", strlen(arr));//随机值1
	//字符数组内'a','b','c','d','e','f'。
	//字符数组后面的'\0'还不知道在什么位置。
	//所以大小为随机值
	printf("%d\n", strlen(arr + 0));///随机值
	//arr+0数组首元素的地址,和arr效果一样
	
	//printf("%d\n", strlen(*arr));//报错
	//*arr为数组首元素'a',ASCII码为97
	//strlen('a')-->strlen(97)
	//地址为97的内存是属于系统的,不允许用户使用。
	//访问的地址不能预测产生什么效果,*arr可视为野指针
	//改代码会报错
	
	//printf("%d\n", strlen(arr[1]));//报错
	//a[1]-->'b',
	//strlen('b')-->strlen(98)
	//产生错误的原因与*a相同
	printf("%d\n", strlen(&arr));//随机值1
	//&a为整个数组的地址,但是地址访问还是从首元素地址开始
	//所以结果也是随机值
	printf("%d\n", strlen(&arr + 1)); //随机值1 - 6
	//&arr+1,跳过的是整的数组,地址为数组后面的地址
	//也为随机值,但是该随机值为随机值1-6
	printf("%d\n", strlen(&arr[0] + 1)); //随机值1 - 1
	//&arr[0]+1是数组第二个元素的地址,该结果也为随机值
	//但是该随机值的为 随机值1-1

	return 0;
}

字符串

字符串"abcdef",存放在字符数组中,f后默认为’\0’,
strlen是求字符串长度的,关注的是字符串中的\0,计算的是\0之前出现的字符的个数
strlen是库函数,只针对字符串
sizeof只关注占用内存空间的大小,不在乎内存中放的是什么
sizeof是操作符

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

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

题目解析

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));//7,数组大小
	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,数组第二个元素地址的大小

	printf("%d\n", strlen(arr));//6,字符串的大小
	printf("%d\n", strlen(arr + 0));//6
	printf("%d\n", strlen(*arr));//错误,*arr=‘a’;访问地址非法
	printf("%d\n", strlen(arr[1]));//错误,arr[1]='b';访问地址非法
	printf("%d\n", strlen(&arr));//6,整个数组的地址,得到的也是最低地址处的地址
	printf("%d\n", strlen(&arr + 1));//随机值,跳过了整个数组不知道是数组后面的地址
	//‘/0’的位置不确定
	printf("%d\n", strlen(&arr[0] + 1));//5,指针跳过1个字符型大小的字节
	//是第二个元素的地址,计算字符串长度6-1

	return 0;
}

常量字符串

需要注意的地方是,char* p = “abcdef”;p是指针变量。 p存储的"abcdef"是字符串首地址,而不是存储的字符串。p+1跳过的是一个字符型所占空间的大小

练习题:

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

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

题目解析:

#include<stdio.h>
#include<string.h>
int main()
{
	char* p = "abcdef";
	printf("%d\n", sizeof(p));//4/8,指针变量的大小
	printf("%d\n", sizeof(p + 1));//4/8,字符串常量第二个字符地址
	printf("%d\n", sizeof(*p));//1,字符串常量首字符的大小
	printf("%d\n", sizeof(p[0]));//1,字符串常量首字符的大小
	printf("%d\n", sizeof(&p));//4/8,字符指针p的地址
	printf("%d\n", sizeof(&p + 1));//4/8,+1跳过一个字符指针的大小,
	//但是该空间指向的不确定是谁。
	printf("%d\n", sizeof(&p[0] + 1));//4/8,p[0]-->*(p+0)-->*p
	//&p[0]+1-->p+1,字符串常量第二个字符地址

	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));//随机值,&p是取出指针变量p的地址,
	//指针变量p存储的是常量字符串的地址,strlen函数把字符串常量的地址
	//看作字符串,这个是一个不确定的值,常量字符串的地址在指针变量中的存储
	//是大端存储还是小端存储还是不确定的,所以结果为随机值
	printf("%d\n", strlen(&p + 1));//随机值,但是与&p两个随机值没有什么关系
	//&p+1是跳过一个指针的大小,指向的该地址与p中不能确定设有'\0'.
	//还是谁没有'\0',还是都没有'\0'.
	printf("%d\n", strlen(&p[0] + 1));//5,&p[0]+1-->p+1

	return 0;
}

二维数组

需要注意的一些知识
二维数组可以看作是一维数组的数组
数组名代表着首元素的地址,二维数组首元素是一维数组,所以二维数组的的数组名代表第一行一位数组的地址
int a[3][4] = { 0 };

  • a[0]可以看作是二维数组第一行一维数组的地址,以此类推a[1],a[2]在这里插入图片描述
  • arr单独在sizeof()内,或者&arr是整个二维数组的地址,其余情况是arr[0]的地址,数据类型int(*)[4]

sizeof()内部表达式是不进行运算的,只是得到该表达式的数据类型

例题:

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

解析:

#include<stdio.h>
#include<stdio.h>
int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//48
	//3*4*4
	printf("%d\n", sizeof(a[0][0]));//4
	//二维数组第一个整形元素的大小
	printf("%d\n", sizeof(a[0]));//16
	//a[0],相当于第一行一维数组名,sizeof(a[0])
	//是二维数组第一行的大小
	printf("%d\n", sizeof(a[0] + 1));//4/8
	//a[0], 相当于第一行一维数组名
	//a[0]+1,相当于二维数组第一行第二个元素地址
	printf("%d\n", sizeof(*(a[0] + 1)));//4
	//*(a[0] + 1)-->a[0][1]
	//计算的是第一行第二个元素的大小
	printf("%d\n", sizeof(a + 1));//4/8
	//a+1二维数组第二行元素的地址
	printf("%d\n", sizeof(*(a + 1)));//16
	//*(a + 1)-->a[1],相当于第二行一维数组名,sizeof(a[1])
	//是二维数组第二行的大小
	printf("%d\n", sizeof(&a[0] + 1));//4/8
	//&a[0]-->&*(a+0)-->a
	//&a[0] + 1-->a+1 
	printf("%d\n", sizeof(*(&a[0] + 1)));//16
	//&a[0] + 1-->a+1
	//*(&a[0] + 1)-->*(a+1)-->a[1]
	//a[1], 相当于第二行一维数组名,sizeof(a[1])
	//是二维数组第二行的大小
	printf("%d\n", sizeof(*a));//16
	//*a-->a[0]是二维数组第一行的地址
	printf("%d\n", sizeof(a[3]));//16
	//a[3]是二维数组第4行的地址
	//虽然二维数组没有第四行,但该代码不是越界
	//sizeof()内部表达式是不进行运算的,只是得到该表达式的数据类型

	return 0;
}
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值