本文介绍了三种经典数组笔试题(一维数组,二维数组,字符数组)以及解析,主要涉及数组和&和sizeof关键字和strlen函数和*解引用之间使用,认识数组名表示的真正含义.全部做完理解之和,对数组名,sizeof和strlen和解引用有个更深层次理解
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 答案:16
解析 : a表示是这个整形数组的数组名 ,而sizeof(数组名),数组名表示的是整个数组,即求的是整个数组的大小==数组所有元素的大小.
这个数组里有4个整形元素 每个元素占4个字节即结果为4*4为16
代码2答案:4/8
解析:a表示的是数组名,而sizeof(数组名+0),此时先运算括号里的数组名+0,数组名和0相加,数组名表示的是数组首元素地址,即一个整形指针,指针加0表示移动0个步长此时不变还是整形1处的地址,
而sizeof(整形指针)是求指针的大小得到的结果和计算机平台有关:32位平台是4字节,64位平台是8字节
代码3答案:4
解析:a是数组名sizeof(*数组名)先算 ( * 数组名),此时数组名表示首元素地址,对首元素地址解引用得到数组里第一个整形空间也就是首元素整形1,此时sizeof(整形)得到的是4
代码4答案:4/8
解析:sizeof(a+1)先算a+1,而数组名+1,数组名表示首元素地址,为1所在整形空间的地址,+1跨越1个步长表示加4个字节,此时为2所在的整形空间地址为整形指针,此时sizeof(指针)得到的结果和计算机平台有关所以为4/8
代码5答案:4
解析:sizeof(a[1])先算里面的a[1],a[1]又等价于*(a+1),表示的是数组名加1 然后解引用,此时数组名表示首元素地址,加1后为2的地址,解引用得到了整形2,sizeof(整形)的结果为4
代码6答案:4/8
解析:sizeof(&a)先算&a 而&数组名中,数组名表示的是整个数组
&整个数组得到的是整形数组指针,则sizeof(指针)得到的结果是4/8
代码7答案:16
解析:sizeof(*&a)中先算 *&a,而 *和&运算符优先级相同,结合性是从右往左,此时先算&a,而&数组名表示&整个数组,得到的是整个数组的地址,再 *数组指针 得到的是整个数组,此时sizeof(整个数组)得到的是整个数组大小为16
代码8答案:4/8
解析:sizeof(&a+1),根据优先级先算&a+1 里的&a,&数组名表示整个数组地址,此时加1跨越整个数组个字节,此时表示的还是一个指针
sizeof(指针)得到的结果是4/8
代码9答案:4/8
解析:sizeof(&a[0]),先算&a[0],a[0]等价于*(a+0)表达的是数组第一个元素,&数组第一个元素得到的是一个整形指针,sizeof(指针)结果为4/8
代码10答案:4/8
解析:sizeof(&a[0]+1),运算顺序先算a[0]为数组第一个元素,再&得到第一个元素地址,整形指针再+1,得到数组第二个元素地址,此时sizeof(地址)得到的结果是4/8
1.先考虑各个运算符的优先级
2.然后注意当出现&数组名 和sizeof(数组名)时数组名表达的含义是整个数组!!!
其他情况下数组名均表示的是数组首元素地址
3.清楚指针的大小和整形的大小和数组的大小
练习一↓
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答案:6
解析:sizeof(arr)表示sizeof(数组名),此时数组名和sizeof连用数组名表示整个数组,而sizeof(整个数组)表示整个数组大小,结果是数组所有元素大小之和,而数组有6个char类型元素 最后结果为6
代码2答案:4/8
解析:sizeof(arr+0),先算arr+0表示数组名加0,此时数组名表示首元素地址,字符地址+0表示移动0个步长结果还是首元素地址,sizeof(字符地址)
结果跟计算机运行平台有关所以是4/8
代码3答案:1
解析:sizeof(*arr)先算 *arr,而 *arr里arr数组名表示首元素地址,即一个字符指针, * 字符指针为解引用访问到的那个首元素字符,sizeof(字符)结果为1
代码4答案:1
解析:sizeof(arr[1])先算arr[1]表示的是数组第二个元素即一个字符,
sizeof(字符)得到的结果是1
代码5答案:4/8
解析:sizeof(&arr),&arr表示的是得到整个数组地址即数组指针,sizeof(指针)结果是4/8
代码6答案:4/8
sizeof(&arr+1) 先算&arr表示数组指针,数组指针加1还是一个指针
sizeof(指针)结果为4/8
代码7答案:4/8
解析:sizeof(&arr[0]+1)先算arr[0]表示第一个元素,&arr[0]表示第一个元素地址 &arr[0]+1表示第二个元素地址,sizeof(指针)结果是4/8
代码8答案:随机值
strlen(arr),是求这个数组里字符串的字符个数,是以’\0’为结束标志
arr表示首元素地址,是传字符指针调用这个函数,然后往后字符并统计字符个数
此时这个数组没有’\0’,最后会越界访问到数组后面的未知空间里的字符,如果不是’\0’仍会计数,直到遇到’\0’返回前面统计的所有字符个数
因为未知的空间里的元素是不确定的,所以不确定’\0’的位置此时得到的是随机值
代码9答案:随机值
解析:strlen(arr+0) arr+0 表示的是首元素地址移动0个步长仍然是首元素地址,和代码8一样的结果最后是随机值
代码10答案:error程序中止运行发生错误
解析:strlen(*arr) 先算 * arr,此时arr表示首元素地址 即a所在内存单元的地址,*arr表示解引用访问到了字符a,而此时字符a作为strlen函数的参数传参,实际上是将字符a类型转换为了字符指针类型
而字符a的ASCLL码值为97,地址是以十六进制形式存在,此时表示为61,假设在32位平台则对应的地址序列为0x00 00 00 61
表示的是在上面那段地址处的内存单元开始往高地址处记录字符个数,直到找到\0,但是 这段空间是计算机内部使用的,是不允许用户通过这种形式解引用访问的,此时会直接报错
代码11答案:error程序中止运行 发生错误
strlen(arr[1]) 先算arr[1]表示的是数组第二个元素,也就是字符b
跟代码10一样,最后被类型转换为了字符指针,以当前字符b对应的十六进制序列表示的内存里的地址,此处空间不能被访问,此时解引用访问的空间会发生错误
代码12答案:随机值
解析:strlen(&arr)先看&arr,&数组名中的数组名表示的是整个数组,此时&整个数组拿到了整个数组地址,是以组成这个数组的的内存单元中起始内存单元也就是地址最低的内存单元的地址作为代表数组指针,此时传参调用strlen函数,形参是用字符指针变量接受,此时相当于这个数组指针被类型转换为字符指针,此时表示的是从第一个字符开始往后找\0并记录字符个数,和代码8一样是随机值
代码13答案:随机值-6
解析:strlen(&arr+1) 先算&arr 表示的整个数组地址,然后&arr+1,表示跨越1个步长,步长大小是指针的类型大小即数组个大小字节,表示加个6个字节,
此时这个指针表示的是整个字符数组最后一个字符地址其后面的地址,最后传参调用strlen函数 被转换为了字符指针,
此时从最后一个字符后面那个空间开始往后找\0,是不确定的值,但是因为代码8是从第一个字符开始找结果为随机值,
而这个代码是从最后一个字符其后的一个空间开始找,得到的结果就是随机值-6
代码14答案:随机值-1
解析:strlen(&arr[0]+1)先看arr[0]得到数组第一个元素,然后&arr[0]得到第一个元素地址,再加1得到第二个元素地址,然后传参调用strlen函数,表示从数组第二个元素开始往后找\0并记录字符个数,代码8中结果是随机值是从第一个元素开始找,而这个代码是从第二个元素开始找,所以结果为随机值减1
笔试题(一)中
1.字符数组是由多个字符组成,最后没有’\0’,此时这个字符数组不代表字符串
2.数组名和&sizeof连用时表示整个字符数组其他情况都是首元素地址
3.考虑运算符优先级
4.strlen是以\0为结束标志,是字符串函数,没有\0则会出现越界访问查找\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
练习2↓ "abcdef"是一个字符串最后隐藏了一个字符’\0’放在数组里实际上是七个元素
代码1答案:7
sizeof(arr)表示sizeof(数组名),此时数组名表示整个数组,sizeof(数组)为整个数组的大小,等于数组所有元素大小之和,而数组内有7个元素,每个元素大小为1,结果为7.
代码2答案:4/8
解析:sizeof(arr+0)先看arr+0,数组名此时表示首元素地址,首元素指针加0还是首元素地址
sizeof(指针)结果和计算机平台有关是4/8
代码3答案:1
解析:*arr的结果为数组首元素sizeof(字符)结果为1
代码4答案:1
解析:arr[1]为数组第二个元素是一个字符 sizeof(字符)结果为1
代码5答案:4/8
解析:&arr 表示整个数组地址,sizeof(指针)结果为4/8
代码6答案:4/8
&arr为整个数组地址 ,+1最后的结果还是一个跨越了1个步长的数组地址,sizeof(指针)结果是4/8
代码7答案:4/8
解析:&arr[0]+1表示的是第二个元素地址,sizeof(指针)结果是4/8
代码8答案:6
解析:strlen(arr)中arr数组名表示首元素地址,是字符指针传参调用strlen函数从首元素开始往后找\0并记录不是\0的字符个数,第七个元素是隐藏字符\0最后得出字符个位为6
代码9答案:6
解析:arr+0表示的还是首元素地址传参调用strlen最后结果是6
代码10答案:error
解析:*arr为首字符,传参调用strlen是将a字符转换为指针形式然后访问其指向的内存空间,其对应的空间是不能被访问的所以报错
代码11答案:error
解析:arr[1]表示数组第二个字符,传给strlen实际也是类型不对应,访问了不能访问的空间,报错
代码12答案:6
解析:&arr得到的是整个数组地址以第一个内存单元地址即首字符地址做代表,传参调用strlen类型会变为字符指针,即从首字符地址开始往后访问空间,记录字符个数,最后遇到\0停止得到的是字符个数6
代码13答案:随机值
解析:&arr+1表示数组指针往后移动了数组个字节即7个字节为\0后面的未知元素的地址,从此位置开始往后找\0找到后最后返回前面统计的非\0字符个数,但是\0此时是未知的,所以结果为随机值
代码14答案:5
解析:&arr[0]表示首元素地址,+1表示第二个元素地址,传参给strlen表示从第二个元素开始往后找\0最后返回的就是期间非\0的字符个数为5
在笔试题(二)中
1."abcdef"存在数组里实际上等价于’a’,‘b’.‘c’.‘d’.‘e’.‘f’.'\0’后面隐藏了\0因为这是字符串要有\0作为结束标志
2.当strlen计算字符串长度会以\0为结束标志
const char *p = "abcdef";
printf("%d\n", sizeof(p));//1
printf("%d\n", sizeof(p+1));//2
printf("%d\n", sizeof(*p));//3
printf("%d\n", sizeof(p[0]));//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+1));//9
printf("%d\n", strlen(*p));//10
printf("%d\n", strlen(p[0]));//11
printf("%d\n", strlen(&p));//12
printf("%d\n", strlen(&p+1));//13
printf("%d\n", strlen(&p[0]+1));//14
代码1答案:4/8
解析:p指的是指针变量p此时存的是字符串首字符地址并不是数组,sizeof(指针)结果是4/8
代码2答案:4/8
解析:p+1表示字符串第二个元素地址,sizeof(指针)结果是4/8
代码3答案:1
解析:*p表示的是第一个字符,sizeof(字符)结果为1
代码4答案:1
解析:p[0]等价于*(p+0)最后的结果是字符串首元素,sizeof(字符元素)结果1
代码5答案:4/8
解析:p是存放首元素地址的字符指针变量.&p得到的是字符指针变量的地址,是一个二级指针,sizeof(地址)结果是4/8
代码6答案:4/8
解析:&p是一个二级指针,+1最后的结果还是一个指针,sizeof(指针)结果是4/8
代码7答案:4/8
解析:&p[0]得到的还是首元素地址,+1是第二个元素地址 还是一个指针 sizeof(指针)结果4/8
代码8答案:6
解析:p是首元素地址是字符指针 传给strlen从a开始往后找\0返回字符串中字符个数为6
代码9答案:5
解析:p+1为第二个元素地址,从字符b作为起始开始往后到\0返回的字符个数为5
代码10答案:error
解析:*p得到的是字符a最后传给strlen和前面一样是无法访问的空间会报错
代码11答案:error
解析:p[0]结果还是字符a 传给strlen是会报错的
代码12答案:随机值
解析:&p是一个二级指针,即p变量是存放着一个十六进制序列表示地址,而&p是指向得到的是p的地址也是一串十六进制序列8个十六进制 2个作为一个字节,传参给strlen转换为字符指针 一个字节一个字节访问即每次访问2个十六进制对应的字母(访问存放p地址的四个内存单元), 不确定地址是什么十六进制,得到的结果也是随机值
代码13答案:随机值
解析:&p+1得到的是存放p空间后面的一个字符指针空间的地址是未知的,访问也是随机值
代码14答案:5
解析:&p[0]+1得到的是是第二个元素地址,传参给strlen 得到的是从第二个元素开始往后找\0期间字符个数为5
笔试题(三)中
1.实际不是字符数组,是一个字符指针变量充当了数组存储了这个字符串,但是存放的仅仅是字符串"abcdef"的首字符a的地址
2.这里没有数组名,p表示的就是首元素地址也就是字符指针和&sizeof连用也不会表示整个字符串
3.有些空间是无法访问的,strlen会为了找字符而非法访问空间会报错
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
代码1答案:48
解析:a表示二维数组数组名,sizeof(数组名)表示数组所有元素大小,每个元素大小为4,有3行四列即12个元素 结果为4*12为48
代码2答案:4
解析:a[0][0]得到的是二维数组第一行第一列的元素,即整形0,sizeof(整形)结果为4
代码3答案:16
解析:a[0]等价于*(a+0),而a数组名这里表示首元素地址,而二维数组首元素为第一行,即表示第一行地址,解引用后表示第一行,sizeof(第一行)表示数组第一行所有元素大小之和,第一行有4个整形,每个整形4个字节 结果为4*4为16
代码4答案:4/8
解析:a[0]表示的是数组第一行,而a[0]表示第一行又等价于是一个一维数组的数组名即第一行数组名,a[0]+1表示一维数组数组名加1 表示的是一维数组首元素地址+1,为第一行第二个元素地址,sizeof(整形指针)结果是4/8
代码5答案:4
解析:a[0]+1表示的是数组第一行第二个元素地址,解引用后得到第二个元素是一个整形
sizeof(整形)结果为4
代码6答案:4/8
解析:a+1 中a表示数组名首元素地址,即第一行的地址,+1移动一个步长大小为16个字节,得到的是数组第二行的地址,sizeof(指针)结果为4/8
代码7答案:16
解析:a+1 得到的是第二行的地址而解引用用得到的是数组第二行,sizeof(二维数组第二行)为数组第二行所有元素类型大小之和为4*4为16
代码8答案:4/8
解析:&a[0]为数组第一行地址,+1后得到是数组第二行地址,sizeof(指针)结果是4/8
代码9答案:16
解析:代码8里&a[0]+1得到的是第二行地址 再解引用得到的就是第二行,sizeof(数组第二行)结果为4*4为16
代码10答案:16
解析:*a表示对数组名解引用,而数组名表示首元素地址 即二维数组第一行地址,解引用得到数组第一行,sizeof(数组第一行)结果为16
代码11答案:16
解析:a[3]等价于*(a+3)表示的是数组第一行地址加3为数组第四行地址解引用得到数组第四行,
虽然没有数组第四行,但是通过数组第一行指针 移动的3个步长得到的指针还是一个一维数组指针,解引用指向的空间和第一行空间一样,虽然是越界 ,但是sizeof只是求相对应大小,结果为4*4为16
1.二维数组首元素是第一行!!!
2.与sizeof二维数组数组名和&二维数组数组名表示的是数组第一行的地址
3.二维数组某一行实际上也可以等价于该行的数组名为一个一维数组数组名
本文介绍了三种数组的经典笔试题以及解析和细节总结,主要是更深层次理解数组名的含义,数组和&和*和sizeof和strlen的运用,
下篇博客会介绍八大经典指针笔试题,这些全部都理解了,对数组,指针和内存会有更深层次的理解…
写文不易,给个一键三连支持下叭~~~