前言
来到第二章,继续学习指针和数组笔试题
第一组题
#include<stdio.h> int main() { char arr[] = "abcdef";//里面的放的是[a b c d e f \0]
printf("%d\n", strlen(arr));
没有单独放在sizeof内部,所以表示首元素地址,strlen统计的是在字符串中\0之前的字符的个数,所以结果是6
2.
printf("%d\n", strlen(arr+0));
arr表示首元素地址,arr+0也表示首元素地址,结果仍是6
3.
//printf("%d\n", strlen(*arr));
arr表示首元素地址,*arr表示首元素,就是字符a,传的是ASCII码值,非法访问内存,是错误代码
4.
printf("%d\n", strlen(arr[1]));
arr[1]是数组第二个元素,也是非法访问内存,是错误代码
5.
printf("%d\n", strlen(&arr));
&arr是数组的地址,但strlen是从首元素地址开始访问的,遇到\0停下,结果是6
6.
printf("%d\n", strlen(&arr+1));
&arr是数组地址,&arr+1跳过整个数组,从\0后面向后访问,后面是未知的,所以是随机值
如下图:
7.
printf("%d\n", strlen(&arr[0]+1));
&arr[0]表示数组首元素地址,&arr[0]+1表示第二个元素地址,意思是从第二个元素地址向后访问,统计了bcdef,5个字符
return 0; }
总结:strlen访问的是地址,统计的是在字符串中\0之前的字符的个数。如果访问的是元素本身,就会造成非法访问内存。
第二组题
int main() { char* p = "abcdef";//[a b c d e f \0]
1.
printf("%d\n", sizeof(p));
p是char类型的指针变量
p是指针变量,大小是4/8个字节
2.
printf("%d\n", sizeof(p + 1));
p是从首元素地址访问的,p+1就是第二个元素地址,就是’b’的地址,是地址就是4/8个字节
如下图:
3.
printf("%d\n", sizeof(*p));
p是首元素地址,*p就是首元素,就是字符’a’,访问的不是地址,是元素本身,计算的是大小,char类型是一个字节
4.
printf("%d\n", sizeof(p[0]));//p[0]=*(p+0)
p[0]是首元素,大小是一个字节
5.
printf("%d\n", sizeof(&p));
p存放的是字符串的地址,&p是char**类型,存放的是p的地址,不是字符串的地址,是地址就是4/8个字节
6.
printf("%d\n", sizeof(&p + 1));
&p是从p的地址开始的,存的是p的整个地址,&p + 1,跳过整个地址,从p的地址后面往后访问地址,是地址就是4/8个字节。
要区分好p+1和&p+1的区别。
如下图:
7.
printf("%d\n", sizeof(&p[0] + 1));
&p[0]指向数组首元素地址,&p[0] + 1指向数组第二个元素地址,得到’b’的地址,是地址就是4/8个字节
return 0; }
总结:p是指针变量,本身就是一个地址,&p也是一个地址,但它们存放的不是同一个地址。p存放的是某个数组的地址,&p存放的是p的地址。
第三组题
int main() { char* p = "abcdef";//[a b c d e f \0]
printf("%d\n", strlen(p));
p是一个指针,存放a b c d e f \0的地址,strlen从a开始访问,遇到\0停下,所以访问了a b c d e f6个字节
2.
printf("%d\n", strlen(p + 1));
p+1是’b’的地址,意思是从p[1]开始向后访问,访问了b c d e f 5个字节3.
// printf("%d\n", strlen(*p));
p是a的地址,*p是字符’a’,非法访问内存
4.
// printf("%d\n", strlen(p[0]));
p[0]=*p=‘a’,所以也是非法访问内存
5.
printf("%d\n", strlen(&p));
p存放的是字符串的地址,&p=char**,存放的是p的地址,但是编译器并不知道p的地址是什么,所以strlen访问到的是一个随机值
6.
printf("%d\n", strlen(&p + 1));
&p+1f跳过了p的地址,从p的地址后面往后访问地址,p后面的地址编译器更不知道了,所以也是随机值
7.
printf("%d\n", strlen(&p[0] + 1));
&p[0]是从’a’的地址向后访问,&p[0] + 1是从’b’的地址向后访问,访问了b c d e f 5个字节
return 0; }
二维数组(难点)
int main() {
int a[3][4] = { 0 };
三行四列的数组,元素都是0
2.
printf("%d\n", sizeof(a));
数组名单独放在sizeof内部,表示整个数组大小,每个元素是整型,344=48
3.
printf("%d\n", sizeof(a[0][0]));
0行0列的元素,大小是4个字节
4.
printf("%d\n", sizeof(a[0]));
把二维数组的每一行看作是一个元素,三行就是三个元素,a[0]就是二维数组的第一行的数组名,注意不是首元素,数组名单独放在sizeof内部,计算整个数组大小,是4*4=16
5.
printf("%d\n", sizeof(a[0]+1));
a[0]没有单独放在sizeof内部,是第一行的首元素地址,a[0]+1是第一行第二个元素的地址,是地址就是4/8个字节
6.
printf("%d\n", sizeof(*(a[0] + 1)));
a[0]+1是第一行第二个元素的地址,*(a[0] + 1)就是第一行第二个元素,大小是4个字节
7.
printf("%d\n", sizeof(a+1));
a是数组首元素的地址,是二维数组第一行的地址,a+1就是二维数组第二行的地址,是地址就是4/8个字节
8.
printf("%d\n", sizeof(*(a + 1)));
a+1是二维数组第二行的地址,(a + 1)是二维数组第二行的元素大小,大小是44=16
9.
printf("%d\n", sizeof(&a[0] + 1));
注意不要把a[0]看作是数组首元素,在二位数组这里,a[0]是数组名,&数组名+1跳过整个数组,表示的是二维数组第二行的地址,是地址就是4/8个字节
10.
printf("%d\n", sizeof(*(&a[0] + 1)));
&a[0] + 1表示的是二维数组第二行的地址,(&a[0] + 1)表示二维数组第二行的元素,计算大小,44=16
11.
printf("%d\n", sizeof(*a));
没有单独放在sizeof内部,没有&修饰,这里的a是二维数组首元素地址,就是第一行的地址,a就是第一行,大小是44=16
12.
printf("%d\n", sizeof(a[3]));
a[3]表示二维数组第四行的数组名,大小是4*4=16
return0;
}
总结
以上就是今天的指针和数组笔试题,二维数组是难点,需要花时间多理解。