指针笔试题解析
一维数组
#include <stdio.h>
int main()
{
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a)); //16
//sizeof(数组名) 数组名单独出现在sizeof里表示的是整个数组所以
//sizeof求出来的是整个数组所占的字节数,因此答案为16
printf("%d\n", sizeof(a + 0)); //4或者8
//数组名不是单独出现在sizeof里面,他表示的是数组首元素的地址。
//a+0相当于不加,所以此题求的是数组首元素地址的大小,地址的大小
//是4或8。
printf("%d\n", sizeof(*a));//4
//*a表示的是数组首元素的地址解引用访问到的是数组首元素1,它是一个整型
//元素,所以此题答案为4
printf("%d\n", sizeof(a + 1)); //4或者8
//a是数组首元素的地址,a+1表示跳过一个整型元素指向数组中2的地址,这里
//也是求地址的大小所以答案为4或者8。
printf("%d\n", sizeof(a[1])); //4
//a[1]访问到的是数组的第二个元素2,是一个整型元素,所以该题答案为4
printf("%d\n", sizeof(&a)); //4或者8
//&a 取出的是整个数组的地址,这里是一个地址,所以该题答案为4或者8
printf("%d\n", sizeof(*&a)); //16
//*& 这两个符号可以抵消,a放在sizeof里面表示的是整个数组,所以该题答案为16
printf("%d\n", sizeof(&a + 1)); //4或者8
//&a取出的是整个数组的地址,整个数组的地址加1,跳过是整个数组,但是它还是一个地址
//所以此题答案为4或者8
printf("%d\n", sizeof(&a[0]));//4或者8
//a[0] 访问到的是数组首元素1,&a[0]取出的是数组第一个元素的地址,它还是一个地址,所以
//该题答案还是为4或者8
printf("%d\n", sizeof(&a[0] + 1)); //4或者8
//数组首元素的地址+1指向了第二个元素的地址,因为还是地址,所以
//该题答案还是4或者8
return 0;
}
运行结果:
字符数组
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));
//sizeof(数组名) 数组名单独出现在sizeof里表示的是整个数组所以
// //sizeof求出来的是整个数组所占的字节数,因此答案6。此数组为字符型数组
printf("%d\n", sizeof(arr + 0)); //4或者8
//此题数组名不是单独出现在sizeof里面,它表示的是数组首元素的地址,
//所以此题的答案为4或者8
printf("%d\n", sizeof(*arr));
//数组首元素地址解引用访问到的是数组首元素a,a是一个字符型元素,所以
//此题答案为1
printf("%d\n", sizeof(arr[1]));
//arr[1]访问的是数组的第二个元素,b是一个字符型元素,所以
//此题答案为1。
printf("%d\n", sizeof(&arr));//4或者8
//&arr取出的是整个数组的地址,它是一个地址,所以此题答案为4或者8
printf("%d\n", sizeof(&arr + 1));
//整个数组的地址+1跳过的是整个数组,但还是一个地址,所以此题答案为
//4或者8
printf("%d\n", sizeof(&arr[0] + 1));
//&arr[0]取出的数组首元素的地址,数组首元素地址+1跳过一个字符型数据,此地址
//指向了数组中的第二个元素,它还是一个地址,所以该题的答案为4或者8
return 0;
}
运行结果:
#include <string.h>
int main()
{
//strlen函数是统计字符串长度的函数,此函数遇到'\0'停止计算
//形参为 const char* p,接收的是一个指针变量
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));
//由于在初始化时未输入'\0' 所以它在字符数组结束时还会向后计算
//直到遇到'\0'才停止,啥时候遇到'\0'我们是不知道的,所以该题答案为
//随机值
printf("%d\n", strlen(arr + 0));
//数组的首元素地址传到strlen中,和上一题是相同的,还是一个随机值
printf("%d\n", strlen(*arr));
//*arr访问到的是一个数组元素a,把一个元素传给strlen它会把a的ascll码当成地址
//导致跳出了数组的存储空间
//此题是不会被运行出来的,会发生错误
printf("%d\n", strlen(arr[1]));
//这题和上题的道理一样,都是把一个元素传给了strlen
printf("%d\n", strlen(&arr));
//从第一个元素开始访问,一直遇到 '\0'后才停止,由于数组中没有'\0'
//所以该题答案为随机值
printf("%d\n", strlen(&arr + 1));
//指向了数组的后面,开始求字符串长度,也是一个随机值,比上一个题的随机值
//永远多6
printf("%d\n", strlen(&arr[0] + 1));
//指向了数组的第二个元素的地址,也是一个随机值,比上两个题多5
return 0;
}
运行结果:
第三个printf可以引发异常
屏蔽掉第三四个printf后,运行结果如下:
可以看到都是随机值
int main()
{
char arr[] = "abcdef";
//默认存入'\0'
//所以arr数组里面存入的是abcdef\0
printf("%d\n", sizeof(arr));
//arr表示的是整个数组,然后这里的答案是7
printf("%d\n", sizeof(arr + 0));
//数组首元素地址4或者8
printf("%d\n", sizeof(*arr));
//*arr访问到的是字符a,答案是1
printf("%d\n", sizeof(arr[1]));
//a[1]访问到的是字符b,答案为1
printf("%d\n", sizeof(&arr));
//&arr取出的是整个数组的地址 答案为 4或者8
printf("%d\n", sizeof(&arr + 1));
//&arr+1还是一个地址 答案为4或者8
printf("%d\n", sizeof(&arr[0] + 1));
//&arr[0]+1还是一个地址,答案为4或者8
return 0;
}
运行结果:
int main()
{
char arr[] = "abcdef";
//默认存入'\0'
//所以arr数组里面存入的是abcdef\0
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
return 0;
运行结果:
int main()
{
char* p = "abcdef";
//是一个指针,然后里面存储的是a的地址
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
return 0;
}
运行结果:
int main()
{
char* p = "abcdef";
//是一个指针,然后里面存储的是a的地址
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));
//答案为随机值
printf("%d\n", strlen(&p + 1));
//随机值
printf("%d\n", strlen(&p[0] + 1));
//答案为5
return 0;
}
二维数组
首先我们来了解二维数组名是什么东西,每一行的数组名是什么。才能了解下面的题。
int main()
{
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));
//表示的是整个二维数组,所以答案为48
printf("%d\n", sizeof(a[0][0]));
//访问到的是第一行第一列的元素,所以答案为4
printf("%d\n", sizeof(a[0]));
//a[0]为第一行一维数组的数组名,代表第一行的整个数组,
//所以答案为16
printf("%d\n", sizeof(a[0] + 1));
//a[0]为第一行首元素的地址+1访问到的是第一行一维数组的第二个元素的地址
//所以答案为4或者8
printf("%d\n", sizeof(*(a[0] + 1)));
//a[0]为第一行首元素的地址+1访问到的是第一行一维数组的第二个元素的地址
//解引用得到的是第二个元素,所以该题答案为4
printf("%d\n", sizeof(a + 1));
//二维数组的数组名代表的是第一行一维数组的地址加一跳过整个一维数组,指向第二行的一维数组
//是一个地址
//所以答案为8
printf("%d\n", sizeof(*(a + 1)));
//上一题解引用访问到了整个数组相当于a[1]第二行的数组名。所以答案为16
printf("%d\n", sizeof(&a[0] + 1));
//&a[0]表示的第一行数组的地址 第一行的地址加一跳过第一行的一维数组指向第二行
//也是为4或者8
printf("%d\n", sizeof(*(&a[0] + 1)));
//解引用访问到的是第二行一维数组,答案为16
printf("%d\n", sizeof(*a));
//访问到的是第一行一维数组,答案为16
printf("%d\n", sizeof(a[3]));
//a[3]访问到的是第三行的一维数组,答案为16
//这里其实不是第三行的一位数组,这是因为
//sizeof只是判断类型的大小,而不管值属性
return 0;
}
运行结果:
每个数组名的层次:
好了就讲到这里。