指针or数组de笔试题

目录

ps前言: 

一.整型数组

​编辑

二.字符数组

<1>没有'\0'标志

 <2>有'\0'标志

<3> 指针变量

三.二维数组


ps前言: 

《1》sizeof(数组名)---数组名表示整个数组----计算整

个数组的大小、

《2》&数组名----数组名表示整个数组,取出的是整个数组的地址

         其他情况下,遇到的数组名都是数组首元素的地址

地址 4/8字节 第几个元素 int 4字节, char 1字节.........

sizeof是操作符/运算符:

sizeof只关注占用内存空间的大小,单位是字节,不关心内存中存放的是什么;;;

strlen是运算符:

strlen是求字符串长度,统计的是\0之前出现的字符个数,一定要找到\0才算结束,可能存在越界访问;;;

一.整型数组

#include<stdio.h>
int main()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a)); //见解析(1)
	printf("%d\n", sizeof(a + 0));//见解析(2)
	printf("%d\n", sizeof(*a));//见解析(3)
	printf("%d\n", sizeof(a + 1));//见解析(4)
	printf("%d\n", sizeof(a[1]));//见解析(5)
	printf("%d\n", sizeof(&a));//见解析(6)
	printf("%d\n", sizeof(*&a));//见解析(7)
	printf("%d\n", sizeof(&a + 1));//见解析(8)
	printf("%d\n", sizeof(&a[0]));//见解析(9)
	printf("%d\n", sizeof(&a[0] + 1));//见解析(10)
}

运行结果如下: 

解析如下 :

解析(1):这里的数组名单独放在sizeof内部,表示整个数组,数组4个元素,每个元素4个字节,所以是16个字节。

解析(2):a+0,没有单独放在sizeof内部,并且没有&数组名,所以表示数组首元素的地址,首元素地址+0,本质是地址。是地址就是4/8字节,地址的大小取决于平台,32位平台下,地址4个字节,64位平台下,地址是8个字节。

解析(3):*a,这里的a表示数组首元素的地址,对首元素地址的*解引用操作,拿到的是第一个元素,所以是4个字节。

解析(4):a+1,没有单独放在sizeof内部,并且没有&数组名,所以表示数组首元素的地址,首元素地址+1表示数组第二个元素的地址,本质是地址,是地址就是4/8字节,地址的大小取决于平台,32位平台下,地址4个字节,64位平台下,地址是8个字节。

解析(5):a[1]可以把它理解成* (a+1),a[1]本质上是数组第二个元素。整型数组每个元素的类型是整型,所以是4字节。

解析(6):&a,这里表示取整个数组地址 ,对数组取地址类型是int(*)[5],表示地址,4/8字节。

解析(7): *&a,可以将 *和&进行抵消,也就是sizeof(a),数组名单独放在sizeof()内部,表示整个数组。也可以理解成先取出了整个数组的地址,在解引用访问整个数组,此时该表达式的类型就是int [4] ,大小就是16字节。

解析(8):&a+1,取出了整个数组的地址,+1跳过整个数组,但是本质还是数组的地址,是地址就是4/8字节。

解析(9):&a[0],取数组首元素的地址,地址是4/8字节

解析(10):&a[0]+1,取数组第二个元素的地址,地址是4/8字节

二.字符数组

<1>没有'\0'标志

#include<stdio.h>
#include<string.h>

char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));//分析请见解析(1)
printf("%d\n", sizeof(arr+0));//分析请见解析(2)
printf("%d\n", sizeof(*arr));//分析请见解析(3)
printf("%d\n", sizeof(arr[1]));//分析请见解析(4)
printf("%d\n", sizeof(&arr));//分析请见解析(5)
printf("%d\n", sizeof(&arr+1));//分析请见解析(6)
printf("%d\n", sizeof(&arr[0]+1));//分析请见解析(7)



printf("%d\n", strlen(arr));//分析请见解析(8)
printf("%d\n", strlen(arr+0));//分析请见解析(9)
printf("%d\n", strlen(*arr));//分析请见解析(10)
printf("%d\n", strlen(arr[1]));//分析请见解析(11)
printf("%d\n", strlen(&arr));//分析请见解析(12)
printf("%d\n", strlen(&arr+1));//分析请见解析(13)
printf("%d\n", strlen(&arr[0]+1));//分析请见解析(14)

解析(1):arr单独放在sizeof内部,表示整个数组的大小,char类型一个字节,一共有6个字符,char[6],则是6字节。

解析(2):arr+0 不是单独放在sizeof内部,且没有&数组名,arr+0 表示的是首元素的地址,此时数组名表示首元素地址,首元素地址+0还是首元素地址。是地址就是4/8字节。

解析(3):*arr,arr表示数组首元素的地址,对地址*解引用,表示的是'a',char类型是字符1个字节。

解析(4):arr[1],对首元素地址进行下标访问操作,访问的是数组第二个元素,即’b’。char的大小是1字节。也可以将arr[1] 理解为* (arr+1)。

解析(5):&arr,取出的使整个数组的地址,类型是char ()[6] 的数组指针。是指针就是4/8字节。

解析(6):&arr+1,此时&arr取出了整个数组的地址,+1后跳过整个数组的地址。类型依旧还是char ()[6] 。是指针大小就是4/8字节。

解析(7):&arr[0]+1,首先,arr和[0]结合,表示数组第一个元素,对其进行取地址操作,取出的是第一个元素的地址。+1后便是第二个元素的地址,是地址就是4/8字节。

解析(8):此时的arr是数组首元素的地址。由于字符数组内没有strlen的停止标识’\0’。故长度不可知,是随机值。

strlen:结束标志是----------'\0' 

解析(9):arr+0,arr+0表示的是首元素的地址向后偏移0个字节,故还是首元素地址。由于字符数组内没有strlen的停止标识’\0’。长度不可知,是随机值。

解析(10):*arr,arr表示首元素地址,对其进行解引用操作,得到’a’,而’a’ 在内存中的值是ascii值97,将97作为参数传给strlen函数会造成访问权限冲突,所以这行代码是错误的。

解析(11):arr[1],arr[1],表示的是第二个元素’b’,'b’的ascii值为98,将98作为参数传给strlen函数会造成访问权限冲突,所以这行代码是错误的。

解析(12):&arr,&arr的类型是char(*)[6],而库函数strlen参数部分为(const char str);,故类型不匹配,不建议这样传参。但是,编译器还是能跑过去,依旧存在’\0’位置不可预知,结果是随机值。

解析(13):&arr+1,依旧是一个字符数组指针,同上述所述,结果依旧是随机值。

解析(14):&arr[0]+1,此时的参数是第二个元素的地址。因为\0’标志位置不可知,所以结果是随机值。

 <2>有'\0'标志

char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//分析请见解析(1)
printf("%d\n", sizeof(arr+0));//分析请见解析(2)
printf("%d\n", sizeof(*arr));//分析请见解析(3)
printf("%d\n", sizeof(arr[1]));//分析请见解析(4)
printf("%d\n", sizeof(&arr));//分析请见解析(5)
printf("%d\n", sizeof(&arr+1));//分析请见解析(6)
printf("%d\n", sizeof(&arr[0]+1));//分析请见解析(7)

printf("%d\n", strlen(arr));//分析请见解析(8)
printf("%d\n", strlen(arr+0));//分析请见解析(9)
printf("%d\n", strlen(*arr));//分析请见解析(10)
printf("%d\n", strlen(arr[1]));//分析请见解析(11)
printf("%d\n", strlen(&arr));//分析请见解析(12)
printf("%d\n", strlen(&arr+1));//分析请见解析(13)
printf("%d\n", strlen(&arr[0]+1));//分析请见解析(14)

解析(1) :arr,此时的数组名单独放在sizeof内部,表示整个数组。“字符串内容”,需要加上’\0’的大小。所以大小是7字节。

解析(2):arr+0,,此时数组名没有单独放在sizeof内部表示首元素的地址,+0依旧是首元素地址。是地址就是4/8字节。

解析(3):*arr,此时数组名表是首元素地址,对首元素进行解引用操作后,访问的是首个元素,即’a’,大小1字节。

解析(4):arr[1],对首元素地址进行下标访问操作,访问的数组第二个元素。因为数组下标从0开始。所以大小是1字节。

解析(5):&arr表示取出整个数组的地址。是地址就是4/8字节。

解析(6):&arr+1,&arr表示取出整个数组的地址,+1跳过整个数组的地址。是地址就是4/8字节。

解析(7):&arr[0]+1,arr首先和[0]结合,表示第一个元素,&第一个元素的地址,+1就是第二个元素的地址。是地址就是4/8字节。

解析(8):arr,没有放在sizeof内部也没有&,此时arr数组名表示首元素的地址。此时,strlen统计的是’\0’字符前的字符个数。长度为6。

解析(9):arr+0,此时arr表示首元素的地址,+0向后偏移0个元素大小,还是首元素地址。strlen统计的长度为6。

解析(10):*arr,解引用操作访问首元素地址,访问的是首元素’a’。字符’a’的ASCII值为97,将97作为地址传给strlen,会造成访问权限冲突,所以这段代码是错误的。

解析(11):arr[1],arr表示首元素地址,通过[]下标访问操作符,访问数组第二个元素,即’b’,‘b’作为参数传递给strlen,传过去的是’b’的ASCII值98,此操作会造成访问权限的冲突,故此代码错误。

解析(12):&arr,取出的是arr字符串数组的地址,类型是char()[7],而strlen所需的参数是char *的指针。类型不匹配,而在一些类型检查比较严谨编译器环境系,这段代码是无法运行的。但是在作者使用的VS2019环境下,编译器会将类型强制转化成char *,从而得到的结果是6.

解析(13):&arr+1,&arr取出了整个字符串数组的地址,+1跳过了整个数组,指向的是数组后内存空间的地址。而该内存空间的内容是不可预知的。所以strlen统计的长是随机值。

解析(14):&arr[0]+1,arr首先和[]结合,表示的是数组第一个元素。取出第一个元素的地址,+1后表示的是第二个元素的地址,即’b’的地址。此时统计字符串长度,从’b’开始统计,长度为5。

<3> 指针变量

int main()
{
	char* p = "abcdef";
	printf("%d\n", sizeof(p));//分析请见解析(1)
	printf("%d\n", sizeof(p+0));//分析请见解析(2)
	printf("%d\n", sizeof(*p));//分析请见解析(3)
	printf("%d\n", sizeof(p[1]));//分析请见解析(4)
	printf("%d\n", sizeof(&p));//分析请见解析(5)
	printf("%d\n", sizeof(&p+1));//分析请见解析(6)
	printf("%d\n", sizeof(&p[0]+1));//分析请见解析(7)
	
	printf("%d\n", strlen(p));//分析请见解析(8)
	printf("%d\n", strlen(p+0));//分析请见解析(9)
	printf("%d\n", strlen(*p));//分析请见解析(10)
	printf("%d\n", strlen(p[1]));//分析请见解析(11)
	printf("%d\n", strlen(&p));//分析请见解析(12)
	printf("%d\n", strlen(&p+1));//分析请见解析(13)
	printf("%d\n", strlen(&p[0]+1));//分析请见解析(14)
	return 0;
}

解析(1):p是一个char* 指针变量,大小是4/8字节。

解析(2):p+0,p是一个char* 指针变量,+0向后偏移一个char* 指针,本质还是指针,是指针就是4/8字节大小。

解析(3):*p,p是存放常量字符串首字符地址的指针,对其进行解引用访问操作后,访问的是常量字符串的首字符’a’,它的大小是1字节。

解析(4):p[1],其实就是对p进行下标访问操作,访问的是p+1地址处的内容,即*(p+1),计算的是’b’的大小,是1字节。

解析(5):&p,取出的是一级指针变量p的地址,类型是二级字符指针,是指针就是4/8字节大小。

解析(6):&p+1,取出p的地址,+1后指向p地址后的一个指针大小的地址,是地址就是4/8字节。
解析(7):&p[0]+1,首先p和[]结合,表示首字符,对其进行取地址操作后,得到的是首字符地址,+1得到第二个字符地址,是地址就是4/8字节大小。
解析(8):p指向的是常量字符串首字符的地址,所以strlen统计的是常量字符串’\0’前的字符个数,长度为6。
解析(9):p+0,表示首元素的地址向后偏移0个字符指针,还是首元素地址,长度是6。
解析(10):*p,p表示首元素地址,*p表示首元素,将首元素’a’作为strlen参数,会造成访问权限冲突,故这是一行错误的代码。
解析(11):p[1],对首元素地址进行下标访问操作,访问的是第二个字符。也就是’b’,,将’b作为strlen参数,会造成访问权限冲突,故这是一行错误的代码。
解析(12):&p,取出的字符指针变量p的地址,故’\0’的位置不可预知。所以长度是随机值。
解析(13):&p+1,&p取出的字符指针变量p的地址,+1后跳过一个指针,指向&P后面的一块内容。而该地址及其后面的内容不可预知,所以长度依旧是随机值。
解析(14):&p[0]+1,,p首先和[]结合,表示的是数组第一个元素。取出第一个元素的地址,+1后表示的是第二个元素的地址,即’b’的地址。此时统计字符串长度,从’b’开始统计,长度为5。

三.二维数组

arr=arr[0] 第一行的数组名,首元素的地址

arr[1] 第二行的数组名,第二行首元素的地址 

int mian()
{
	int a[3][4] = { 0 };
	
	printf("%d\n", sizeof(a));//分析请见解析(1)
	printf("%d\n", sizeof(a[0][0]));//分析请见解析(2)
	printf("%d\n", sizeof(a[0]));//分析请见解析(3)
	printf("%d\n", sizeof(a[0] + 1));//分析请见解析(4)
	printf("%d\n", sizeof(*(a[0] + 1)));//分析请见解析(5)
	printf("%d\n", sizeof(a + 1));//分析请见解析(6)
	printf("%d\n", sizeof(*(a + 1)));//分析请见解析(7)
	printf("%d\n", sizeof(&a[0] + 1));//分析请见解析(8)
	printf("%d\n", sizeof(*(&a[0] + 1)));//分析请见解析(9)
	printf("%d\n", sizeof(*a));//分析请见解析(10)
	printf("%d\n", sizeof(a[3]));//分析请见解析(11)
	
	return 0;
}

 解析(1):二维数组数组名单独放在sizeof内部,表示整个数组,大小是48字节。
解析(2):a[0][0] 表示第一行第一个元素,大小是4字节。
解析(3):a[0],数组名表示第一行的地址,类型是int()[4],对其进行下标访问操作,访问的是第一行数组,类型是int[4],所以计算的大小是16字节。
解析(4):a[0] + 1,a[0]是第一行数组名,但是数组名没有单独放在sizeof内部,是第一行的地址,+1跳过一行,表示是第二行的地址,是地址就是4/8字节。
解析(5):*(a[0] + 1),首先根据上述分析,a[0] + 1是第二行的地址。对其进行解引用操作后,得到的是第二行的数组名,所以大小是16字节。
解析(6):a + 1,此时数组名表示第一行的地址,+1后表示第二行的地址。是地址就是4/8字节。
解析(7):*(a + 1),a+1表示第二行的地址,对其解引用后,表示整个第二行,大小是16字节。
解析(8):&a[0] + 1,a表示第一行的地址,和[]结合后表示整个第一行,对其&拿到的是第一行的地址,+1 表示第二行的地址。是地址就是4/8字节。
解析(9):(&a[0] + 1),上述分析&a[0] + 1为第二行的地址,对其进行解引用操作后表示的是整个第二行,大小是16字节。
解析(10):*a,此时a表示第一行的地址,对其进行解引用操作,拿到的是整个第一行,大小是16字节。
解析(11):a[3],上述分析a[3]表示整个第4行,但是a[3][4]没有第4行,但是这不影响sizeof计算大小,因为sizeof计算的是类型的大小,所以是16字节。

我希望我能 越努力越幸运!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值