目录
- 前言
- 题目
-
- 题目1
- 题目2
- 题目3
前言
在学习完C语言的初阶以及进阶以后,我们需要一些习题来检验自己的学习成果,下面将以一些笔试题和面试题来分析。
在题目的分析中如有错误,欢迎指正。
题目
题目1
int main() {
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));//6
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
//strlen函数输入地址,找到0为止
printf("%d\n", strlen(arr));//随机值b
printf("%d\n", strlen(arr + 0));//随机值b
printf("%d\n", strlen(*arr));//错误
printf("%d\n", strlen(arr[1]));//错误
printf("%d\n", strlen(&arr));//随机值b
printf("%d\n", strlen(&arr + 1));//随机值b-6
printf("%d\n", strlen(&arr[0] + 1));//随机值b-1
return 0;
}
sizeof是一个操作符,strlen是C语言库函数,接受的是一个地址
在前面我们知道数组名代表首元素地址,但是有例外,例如sizeof和数组直接使用时,这时候数组名代表整个数组。
经过我们分析可以知道
- arr直接使用代表整个数组,sizeof(arr)的值是6;
- arr+0是一个地址,所以sizeof(arr+0)的值是4或8,具体答案取决32或64平台
- *arr是首元素a的引用,所以sizeof(*arr)的值是1;
- arr[0]也是首元素a,与上面相同,它的值也是1;
- &arr是一个地址,所以它的值是4或者8;
- &arr+1是一个地址,所以它的值是4或者8;
- &arr[0]+1也是一个地址,所以它的地址是4或者8;
具体答案是不是我们分析的那样,用VS2019编译器进行验证
接下来分析strlen函数
我们知道strlen接受字符串地址,然后往后找到/0结束
但是我们在题目中初始化时没有给’\0’,这样就会造成他会一直往后走找到结束标志’\0’。
- arr是首元素地址,但是我们不知道结束的0在哪,所以长度未知,设为len
- arr+0也是首元素地址,未知结束标志在哪,长度未知,并且和上一个长度相同,也是len
- *arr是什么?它是首元素a,数值97,不是一个地址,所以会报错
- arr[1]是元素b,不是一个地址,也会报错
- &arr是一个地址,是整个元素地址,但是和首元素地址相同,所以它的值也是len
- &arr+1是一个地址,但是它不是第二个元素的地址,而是跳过了整个数组的地址,指向f后面一个元素地址,跳过了6个元素,所以它的值len-6
- &arr[0]+1是一个地址,这个才是指向了第二个元素地址,值是len-1
让我们通过VS2019编译器进行验证
由于3,4两行代码会报错从而导致程序终止运行,我们将它屏蔽掉,最右边是运行结果,这与我们的分析是一致的。
题目2
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));//错误
//printf("%d\n", strlen(arr[1]));//错误
printf("%d\n", strlen(&arr));//6
printf("%d\n", strlen(&arr + 1));//随机
printf("%d\n", strlen(&arr[0] + 1));//5
}
这题和上面题只是多了一个结束的0,在结果上略有不同。
所以它包含7个元素,这和上面的多了一个’\0’
所以sizeof(arr)的值是7
strlen函数我们知道了结束的标志在哪里,所以可以轻松判断字符串长度
而&arr+1跳过了整个字符串,下一个’\0’是未知的,所以是随机值
题目3
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
printf("%d\n", sizeof(&p + 1));//4/8
printf("%d\n", sizeof(&p[0] + 1));//4/8
printf("%d\n", strlen(p));//6
printf("%d\n", strlen(p + 1));//5
//printf("%d\n", strlen(*p));
//printf("%d\n", strlen(p[0]));
printf("%d\n", strlen(&p));//随机值a
printf("%d\n", strlen(&p + 1));//随机值b
printf("%d\n", strlen(&p[0] + 1));//5
}
我们需要知道的是,这是一个常量字符串,一个cha* 的指针不可能包含整个字符串,它指向的是首元素a。也就是说*p==a,p是首元素的地址。
我们知道sizeof(地址)的值是4或者8
p,p+1,&p,&p+1,&p[0]+1它们都是地址
*p和p[0]代表首元素a,所以所占空间是1
当首元素的地址传进strlen函数时,直到往后找到’\0’,由此我们可以判断strlen§==6,strlen(p+1)==5;
这里需要注意的是,我们这里&p和上面一个题的&arr是两个概念,&p是地址的地址,指针p的地址,与原来字符串数组关系不大了。