玩透指针系列(四)——这些指针和数组的题,你都会了吗?

指针和数组笔试题

题目1

//一维整型数组
#include<stdio.h>
int main()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a)); //16
    //sizeof(数组名)中的数组名为整个数组,计算的为整个数组的大小,单位为字节 
    
	printf("%d\n", sizeof(a + 0)); //4
	//sizeof(a + 0)中a为数组首元素地址,a+0 为下表为0的元素的地址,即计算地址的大小,所以为4
	
	printf("%d\n", sizeof(*a)); //4
	//*a 为对首元素地址解引用,得到第一个元素,为整型,大小为4个字节
	
	printf("%d\n", sizeof(a + 1)); //4 (同上)
	
	printf("%d\n", sizeof(a[1])); //4
	//a[1] == *(a+1) 为数组中下标为1的元素
	
	printf("%d\n", sizeof(&a)); //4
	//&a 为取出整个数组的地址,大小为4字节
	
	printf("%d\n", sizeof(*&a)); //16
	//*&a = *(&a) = a ,先取出整个数组的地址,在解引用,就得到a (同上)
	
	printf("%d\n", sizeof(&a + 1)); //4
	//&a+1 为整个数组向后移动一个数组大小后的地址,本质仍为地址,大小为4字节
	
	printf("%d\n", sizeof(&a[0])); //4
	//&a[0] 为数组中第一个元素的地址
	
	printf("%d\n", sizeof(&a[0] + 1)); //4
    //&a[0]+1 为数组中第二个元素的地址
    
	return 0; 
}

注:运行的程序是在32位的平台上
在这里插入图片描述
关键点:明确 sizeof 计算的是数组的大小还是数组中元素的大小,亦或是地址的大小是解题的关键。

题目2

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr)); //6
	//计算整个数组大小
	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
	//计算下标为1的元素地址的大小
	return 0;
}

在这里插入图片描述

提示:strlen函数的功能
在这里插入图片描述
即传入的为参数会被 char型的形参接收(被强制类型转换为char 型),当遇到‘\0’ 就会返回字符串或字符数组的长度。

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
    printf("%d\n", strlen(arr)); //随机值
    //strlen 函数遇到‘\0’就停止,而arr数组中没有‘\0’,所以strlen函数会一直向后寻找,直到找到‘\0’为止,所以最后结果为随机值
    
	printf("%d\n", strlen(arr + 0)); //随机值
	//arr+0 为数组首元素的地址,即strlen函数从首元素开始找(同上)
	
	//printf("%d\n", strlen(*arr)); //err
	//传入函数的为首元素,即为‘a’,而strlen函数接收到的为字符‘a’的ASCII码值为97,函数就把97当作地址,此时的函数求出数组的长度,所以会出错
	
	//printf("%d\n", strlen(arr[1])); //err(同上)
	
	printf("%d\n", strlen(&arr)); //随机值
	//传入函数的为整个数组arr的地址,但是strlen函数会将数组arr的地址强制
	//类型转换为char*型,转换后的结果为一个char*型的指针,即char*arr,
	//为  首元素的地址,所以结果仍为随机值
	
	printf("%d\n", strlen(&arr + 1)); //随机值-6
	//同上,传入的为整个数组向后移动一个数组长度后的地址,传入函数后会发
	//生强制类型转换,结果为随机值,但是因为向前走过一个数组的长度,所以
	//为随机值-6
	
	printf("%d\n", strlen(&arr[0] + 1)); //随机值-1
	//传入的为第下标为1的元素的地址,从此元素开始求长度,所以为 随机值-1
	
	return 0;
}

在这里插入图片描述

题目3

int main()
{
	char arr[] = "abcdef";//arr中实际存放的为:" a b c d e f \0 "
	
	printf("%d\n", sizeof(arr));//7
	//arr中实际存放的为7个字符,所以结果为7
	
	printf("%d\n", sizeof(arr + 0));//4
    //arr+0 为首元素地址,计算地址的大小,即为4
    
	printf("%d\n", sizeof(*arr));//1
	//计算首元素的大小,首元素为char型,大小为1个字节
	
	printf("%d\n", sizeof(arr[1]));//1(同上)

	printf("%d\n", sizeof(&arr));//4
	//计算整个数组地址的大小,但本质上仍为指针,所以为4
	
	printf("%d\n", sizeof(&arr + 1));//4(同上)
	
	printf("%d\n", sizeof(&arr[0] + 1));//4
	//计算下标为1的元素地址的大小,为4
	
	return 0;
}

在这里插入图片描述

int main()
{
	char arr[] = "abcdef";//(同上)
	
    printf("%d\n", strlen(arr));//6
    //arr数组中字符‘f’后就为‘\0’,函数读取到后就停止,所以为6
    
	printf("%d\n", strlen(arr + 0));//6
	//arr+0为首元素地址(同上)
	
	//printf("%d\n", strlen(*arr));//err
	//函数会见字符‘a’的ASCII码值当成地址,所以会显示错误
	
	//printf("%d\n", strlen(arr[1]));//err(同上)
	
	printf("%d\n", strlen(&arr));//6
	//函数会将&arr强制类型转换为数组首元素地址,所以结果仍为6
	
	printf("%d\n", strlen(&arr + 1));//随机值
	//&arr+1 为整个数组向后走一步后的地址(同上)
	
	printf("%d\n", strlen(&arr[0] + 1));//5
    //函数从数组中下标为1的元素向后求长度,结果为5
    
	return 0;
}

在这里插入图片描述

题目4

提示:
对于定义的数组指针p: char* p = “abcdef” ,可知指针p指向的为字符串的首元素,即p为首元素地址。实际的在内存中为:

在这里插入图片描述

int main()
{
	char* p = "abcdef";
	printf("%d\n", sizeof(p));//4
	//p为指针,大小为4个字节
	
	printf("%d\n", sizeof(p + 1));//4(同上)
	
	printf("%d\n", sizeof(*p));//1
	//*p为第一个字符a,大小为1字节
	
	printf("%d\n", sizeof(p[0]));//1(同上)
	
	printf("%d\n", sizeof(&p));//4
	//&p为指针p的地址,仍为地址,大小4字节
	
	printf("%d\n", sizeof(&p + 1));//4
	//&p+1为地址(同上)
	
	printf("%d\n", sizeof(&p[0] + 1));//4
	//计算的为字符数组中下标为1的元素的地址,大小为4
	
	return 0;
}

在这里插入图片描述

int main()
{
	char* p = "abcdef";//(同上)
    printf("%d\n", strlen(p));//6
    //p为字符串首字符地址,所以结果为6
    
	printf("%d\n", strlen(p + 1));//5
	//p+1 为首字符向后走一步后的地址,结果为5
	
	//printf("%d\n", strlen(*p));//err
	//*p=a, 传入函数内的为a的ASCII码值(同上)
	
	//printf("%d\n", strlen(p[0]));//(同上)
	
	printf("%d\n", strlen(&p));//随机值
	//&p为取出字符指针p的地址,而函数利用p的地址向后求长度时,并不知道‘\0’的位置,所以结果为随机值
	
	printf("%d\n", strlen(&p + 1));//随机值
	//&p+1 为取出p的地址后再向后移动指针p大小的长度后的地址(同上)
	
	printf("%d\n", strlen(&p[0] + 1));//5
	//从字符串中第二个字符开始求长度,所以结果为5
	
	return 0;
}

在这里插入图片描述

题目5

补充,对于定义的二维数组 int a[3][4] = { 0 },在内存中的存储情况为
在这里插入图片描述

int main()
{
	//二维数组
	int a[3][4] = { 0 };
	
	printf("%d\n", sizeof(a));//48
	//sizeof内部放入单个数组名代表计算整个数组大小,所以大小为4*12=48
	
	printf("%d\n", sizeof(a[0][0]));//4
	//计算第一个元素的大小
	
	printf("%d\n", sizeof(a[0]));//16
	//a[0]表示二维数组中的第一行,所以计算的是第一行的大小,为4*4=16
	
	printf("%d\n", sizeof(a[0] + 1));//4
	//a[0]没有作为二维数组的第一行数组名单独放在sizeof内部,也没有取地址,
	//所以a[0]在这里代表的就是第一行的首元素的地址,a[0]+1就代表第一行第
	//二个元素的地址,因为是地址,所以大小是4(字节)
	
	printf("%d\n", sizeof(*(a[0] + 1)));//4
	//*(a[0]+1)为第一行第二个元素(结合上题解析)
	
	printf("%d\n", sizeof(a + 1));//4
	//a为二维数组的数组名,没有单独放在sizeof内部,也没有取地址,所有这
	//里的a表示数组首元素地址,即:第一行的地址,a+1就为二维数组第二行地址
	
	printf("%d\n", sizeof(*(a + 1)));//16
	//*(a + 1)为二维数组第二行,所以计算的为第二行大小(结合上题解析)
	
	printf("%d\n", sizeof(&a[0] + 1));//4
	//&a[0]为取出第一行地址,所以&a[0] + 1 为第二行地址
	
	printf("%d\n", sizeof(*(&a[0]+1)));//16
	//*(&a[0]+1)为对第二行的地址解引用,得到第二行,所以计算的是第二行大小
	
	printf("%d\n", sizeof(*a));//16
	//a为首元素(第一行)地址,所以*a就为第一行,所以计算的是第一行大小 
	
	printf("%d\n", sizeof(a[3]));//16
	//a[3]其实是第四行数组名(如果有的话),实际上不存在,但是在sizeof内
	//部能通过类型计算大小,因为a[3]的类型为 int [4] ,所以大小为4*4=16
	
	return 0;
}

在这里插入图片描述

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

  • 23
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值