C语言必刷经典习题

目录

习题一:关于一维数组sizeof的相关计算

解答:

运行结果(小编的是x64环境)

习题二:关于字符数组与库函数strlen的相关计算

注意:库函数strlen相关介绍

解答:


习题一:关于一维数组sizeof的相关计算

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(a),这里的a代表整个数组,所以答案为16字节

(二)、为sizeof(a+0),很多伙伴可能会觉得a和a+0不是一回事吗?还真不是一回事,sizeof里面只有单独的数组名时,算的才是整个数组的大小,而这里是a+0,代表的是首元素的地址+0,结果还是首元素的地址,所以答案为4或8字节(x86环境下是4,x64环境下是8)。

(三)、为sizeof(*a),而不是上述两种特例,所以这里是对首元素的地址解引用,得到首元素的值,又因为这是一个整型数组,所以答案为4字节

(四)、为sizeof(a+1),与(二)类似,是首元素的地址+1,得到第二个元素的地址,是地址大小就为4或8字节,所以答案为4或8字节

(五)、为sizeof(a[1]),很显然就是第二个元素,所以答案为4字节,这里有一个公式可以了解

                                                           a[n]=*(a+n)

(六)、为sizeof(&a),大家可别把上述两个特例搞混了,这里&a取的虽然是整个数组的地址,但数组的地址不也还是地址吗,是地址大小就为4或8字节,所以答案为4或8字节

(七)、为sizeof(*&a),这道题有两种思路:

①:从操作符的角度:*和&是可以相互抵消的,所以sizeof(*&a)相当于sizeof(a),所以这里的数组名a代表整个数组,所以答案为16字节

②:从数组指针的角度:&a,取的是数组的地址,所以应该放在一个数组指针里面,那对数组指针解引用得到什么呐?我们知道对整型指针解引用得到一个整形,对字符指针解引用得到一个字符,所以对一个数组指针解引用自然而然得到一个数组咯,所以答案为16字节

(八)、为sizeof(&a+1),与(六)类似,&a,取的是整个数组的地址,地址+1还是地址,是地址大小就为4或8字节,所以答案为4或8字节

(九)、为sizeof(&a[0]),这里很显然&a[0]是首元素的地址,是地址大小就为4或8字节,所以答案为4或8字节

(十)、为sizeof(&a[0]+1),与(九)类似,&a[0]是首元素的地址,&a[0]+1则是第二个元素的地址,所以答案为4或8字节

运行结果(小编的是x64环境)

第一题到此结束,你能对多少个呐?

习题二:关于字符数组与库函数strlen的相关计算

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

int main()
{
	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));//(七)
	return 0;
}

注意:库函数strlen相关介绍

①:库函数strlen的作用是计算字符串长度的,参数接收的是字符串的首地址。

②:计算规则:统计字符串中‘\0’之前的字符个数,若没有找到\0,则会一直向后统计。

③:函数声明:

size_t strlen ( const char * str );

解答:

(一)、为strlen(arr),这里arr代表首元素地址,但字符数组初始化有很多种,如用例初始化,很多伙伴都会觉得答案是6,实则不然,这种初始化方式不会自动在末尾放‘\0’,所以strlen会一直统计 下去,直到找到'\0',所以答案为随机值

(二)、为strlen(arr+0),arr代表首元素地址,arr+0也代表首元素地址,所以和(一)相同,答案也是随机值

(三)、为strlen(*arr),很多人可能是这样想的,arr代表首元素地址,解引用arr就代表首元素,而strlen是求字符串长度,所以结果为1,但实则不然,我们注意看strlen函数的声明中的形参是“const char* str”,意为着我们需要传的实参是待求长度的字符串的首地址,所以当我们把首元素传给strlen,即把字符‘a’传给strlen,而字符‘a’的ASCII码为97,所以如果把字符'a‘传给strlen,strlen会把'97‘当作地址00 00 00 97统计下去,而这份空间不属于我们,所以存在非法访问内存的问题,所以这种这写法是错误写法

(四)、为strlen(arr[1]),这种写法和(三)类似,把字符'b'传给strlen,所以存在非法访问内存的问题,所以这种写法是错误的

(五)、为strlen(&arr),这里&arr取的是整个数组的地址,而数组的地址与数组首元素地址是相同的,所以strlen会从首元素开始统计,直到找到'\0',所以情况和(一)一样是随机值

(六)、为strlen(&arr+1),这里很多伙伴以为&arr+1是第二个元素的地址,实则不然,首先&arr,取的是数组的地址,而数组的地址就应该放在数组指针里面,我们又知道指针类型决定了指针解引用访问权限和加减整数能跳过的步伐,整型解引用就访问一个整型,整型指针+1就跳过一个整型的空间(4字节),所以这里同理,数组指针+1就会跳过一个数组的空间,所以strlen会从数组的末尾即字符‘f’的后面一份空间开始统计,因为不知道什么时候能遇见'\0',所以结果也是随机值

(七)、为strlen(&arr[0]+1),这里&arr[0]取的是首元素的地址,所以用字符指针接收,所以字符指针+1只跳过1字节,所以&arr[0]+1访问的是第二个元素的地址,但依旧不知道什么时候遇见'\0',所以结果也为随机值

本次知识到此,后续小编会继续更新!

猜你喜欢

转载自blog.csdn.net/hffh123/article/details/132279621