零基础自学C语言|大厂指针笔试题
2023-12-14 23:08:54
在正片开始之前,我们先回顾一下strlen和sizeof的区别:
📌sizeof
在学习操作符的时候,我们学习了?sizeof?,?sizeof?计算变量所占内存内存空间大小的,单位是字节,如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小。
sizeof?只关注占用内存空间的大小,不在乎内存中存放什么数据。
比如:
int main()
{
int a = 0;
printf("%zd\n", sizeof(a));
printf("%zd\n", sizeof(int));
printf("%zd\n", sizeof a);
return 0;
}
总结:
- sizeof是操作符
- sizeof计算操作数所占内存的大小,单位是字节?
- 不关注内存中存放什么数据
📌strlen
strlen?是C语言库函数,功能是求字符串长度。函数原型如下:
?
size_t?strlen?(const?char? * str?);
统计的是从?strlen?函数的参数?str?中这个地址开始向后,\0之前字符串中字符的个数。strlen函数会一直向后找\0字符,直到找到为止,所以可能存在越界查找。
int main()
{
char arr1[] = { 'a','b','c' };
char arr2[] = "abc";
printf("%zd\n", sizeof(arr1));
printf("%zd\n", sizeof(arr2));
printf("%d\n", strlen(arr1));
printf("%d\n", strlen(arr2));
return 0;
}
总结:
- strlen是库函数,使用需要包含头文件?string.h
- srtlen是求字符串长度的,统计的是\0?之前字符的隔个数
- 关注内存中是否有\0,如果没有\0,就会持续往后找,可能会越界
正片开始
📌数组与指针的笔试题解析
📍一维数组
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;
}
?解析:
int main()
{
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));
//a是数组名sizeof(数组名)代表计算数组的长度,结果为16
printf("%d\n", sizeof(a + 0));
//a是数组名,没有出现sizeof(数组名)或&(数组名)的情况(特殊情况),所以代表的是首元素的地址,+0后还是首元素的地址,sizeof(地址)的结果为4或8
printf("%d\n", sizeof(*a));
//没有出现特殊情况,a代表首元素的地址*a就代表首元素,所以结果是4
printf("%d\n", sizeof(a + 1));
//没有出现特殊情况,a+1代表第二个元素的地址,所以结果是4或8
printf("%d\n", sizeof(a[1]));
//没有出现特殊情况,a[1]代表第二个元素,所以结果是4
printf("%d\n", sizeof(&a));
//出现了&(数组名)的情况,&a代表整个数组的地址,整个数组的地址也是地址,所以结果是4或8
printf("%d\n", sizeof(*&a));
//*&a相当于a。出现了sizeof(数组名)的情况,代表计算数组的长度,结果为16
printf("%d\n", sizeof(&a + 1));
//出现了&(数组名)的情况,&a+1代表整个数组后的地址,所以结果是4或8
printf("%d\n", sizeof(&a[0]));
//没有出现特殊情况,a[0]代表首元素,&a[0]代表首元素的地址,所以结果是4或8
printf("%d\n", sizeof(&a[0] + 1));
//没有出现特殊情况,&a[0]代表首元素的地址,&a[0]+1代表第二个元素的地址,所以结果是4或8
return 0;
}
运行结果:?
📍字符数组
代码1:
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));
return 0;
}
?解析:
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%zd\n", sizeof(arr));
//出现了sizeof(数组名)的情况,代表计算数组的长度,结果为6
printf("%zd\n", sizeof(arr + 0));
//没有出现特殊情况,arr代表首元素的地址,所以结果是4或8
printf("%zd\n", sizeof(*arr));
//没有出现特殊情况,*arr代表首元素,所以结果是1
printf("%zd\n", sizeof(arr[1]));
//没有出现特殊情况,arr[1]代表第二个元素,所以结果是1
printf("%zd\n", sizeof(&arr));
//出现了&(数组名)的情况,&arr代表整个数组的地址,整个数组的地址也是地址,所以结果是4或8
printf("%zd\n", sizeof(&arr + 1));
//出现了&(数组名)的情况,&a+1代表整个数组后的地址,所以结果是4或8
printf("%zd\n", sizeof(&arr[0] + 1));
//没有出现特殊情况,&arr[0]代表首元素的地址,&arr[0]+1代表第二个元素的地址,所以结果是4或8
return 0;
}
运行结果:
代码2:
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;
}
?解析:
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));
//arr是首元素的地址,数组中没有\0,因此结果是随机值
printf("%d\n", strlen(arr + 0));
//arr+0是首元素的地址,数组中没有\0,因此结果是随机值
printf("%d\n", strlen(*arr));
//*arr是首元素,但是strlen要求输入地址,因此结果会发生错误
printf("%d\n", strlen(arr[1]));
//arr[1]是第二个元素,但是strlen要求输入地址,因此结果会发生错误
printf("%d\n", strlen(&arr));
//出现了& (数组名)的情况,& arr代表整个数组的地址,数组中没有\0,因此结果是随机值
printf("%d\n", strlen(&arr + 1));
//出现了& (数组名)的情况,& arr+1代表整个数组之后的地址,不一定有没有\0,因此结果是随机值
printf("%d\n", strlen(&arr[0] + 1));
//&arr[0]代表首元素的地址,&arr[0] + 1代表第二个元素的地址,数组中没有\0,因此结果是随机值
return 0;
}
运行结果(去掉两行报错代码):
?代码3:
int main()
{
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));
return 0;
}
解析:
int main()
{
char arr[] = "abcdef";//数组中共有七个元素:a、b、c、d、e、f、\0
printf("%d\n", sizeof(arr));
//出现了sizeof(数组名)的情况,代表计算数组的长度,结果为7
printf("%d\n", sizeof(arr + 0));
//没有出现特殊情况,arr代表首元素的地址,所以结果是4或8
printf("%d\n", sizeof(*arr));
//没有出现特殊情况,*arr代表首元素,所以结果是1
printf("%d\n", sizeof(arr[1]));
//没有出现特殊情况,arr[1]代表第二个元素,所以结果是1
printf("%d\n", sizeof(&arr));
//出现了&(数组名)的情况,&arr代表整个数组的地址,整个数组的地址也是地址,所以结果是4或8
printf("%d\n", sizeof(&arr + 1));
//出现了&(数组名)的情况,&a+1代表整个数组后的地址,所以结果是4或8
printf("%d\n", sizeof(&arr[0] + 1));
//没有出现特殊情况,&arr[0]代表首元素的地址,&arr[0]+1代表第二个元素的地址,所以结果是4或8
return 0;
}
运行结果:
代码4:
int main()
{
char arr[] = "abcdef";
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;
}
解析:
int main()
{
char arr[] = "abcdef";//数组中共有七个元素:a、b、c、d、e、f、\0
printf("%d\n", strlen(arr));
//没有出现特殊情况,arr代表首元素的地址,strlen从首元素开始计算,直到遇见\0,所以结果为6
printf("%d\n", strlen(arr + 0));
//没有出现特殊情况,arr+0代表首元素的地址,所以结果为6
printf("%d\n", strlen(*arr));
//*arr是首元素,但是strlen要求输入地址,因此结果会发生错误
printf("%d\n", strlen(arr[1]));
//arr[1]是第二个元素,但是strlen要求输入地址,因此结果会发生错误
printf("%d\n", strlen(&arr));
//出现了& (数组名)的情况,& arr代表整个数组的地址,数组中没有\0,因此结果是随机值
printf("%d\n", strlen(&arr + 1));
//出现了& (数组名)的情况,& arr+1代表整个数组之后的地址,不一定有没有\0,因此结果是随机值
printf("%d\n", strlen(&arr[0] + 1));
//&arr[0]代表首元素的地址,&arr[0] + 1代表第二个元素的地址,因此结果是5
return 0;
}
运行结果(去掉两条错误代码):?
代码5:
?
int main()
{
char* p = "abcdef";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p + 1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p + 1));
printf("%d\n", sizeof(&p[0] + 1));
return 0;
}
解析:
int main()
{
char* p = "abcdef";//p代表了a的地址
printf("%zd\n", sizeof(p));//没有出现特殊情况,p代表a的地址,所以结果是4或8
printf("%zd\n", sizeof(p + 1));//没有出现特殊情况,p+1代表b的地址,所以结果是4或8
printf("%zd\n", sizeof(*p));//没有出现特殊情况,*p代表字符a,所以结果是1
printf("%zd\n", sizeof(p[0]));//没有出现特殊情况,p[0]代表*(p+0),所以结果是1
printf("%zd\n", sizeof(&p));//没有出现特殊情况,&p是二级指针,结果是4或8
printf("%zd\n", sizeof(&p + 1));//没有出现特殊情况,&p+1是二级指针,结果是4或8
printf("%zd\n", sizeof(&p[0] + 1));//没有出现特殊情况,&p[0]+1=&*(p+0)+1,结果还是指针,指向了b,所以结果是4或8
return 0;
}
运行结果:
代码6:
int main()
{
char* p = "abcdef";
printf("%d\n", strlen(p));
printf("%d\n", strlen(p + 1));
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));
return 0;
}
解析:
int main()
{
char* p = "abcdef";//常量字符串,且后面有\0
printf("%d\n", strlen(p));
//p是a的地址,所以结果为6
printf("%d\n", strlen(p + 1));
//p+1是b的地址,所以结果是5
printf("%d\n", strlen(*p));
//*p是a,不是地址,结果error
printf("%d\n", strlen(p[0]));
//p[0]也是a,不是地址,结果error
printf("%d\n", strlen(&p));
//&p代表p的地址,结果为随机值
printf("%d\n", strlen(&p + 1));
//&p+1代表p后面的地址,结果为随机值
printf("%d\n", strlen(&p[0] + 1));
//&p[0]+1代表b的地址,结果是5
return 0;
}
运行结果(去掉两行错误代码):
📍二维数组
int main()
{
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a[0][0]));
printf("%d\n", sizeof(a[0]));
printf("%d\n", sizeof(a[0] + 1));
printf("%d\n", sizeof(*(a[0] + 1)));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(*(a + 1)));
printf("%d\n", sizeof(&a[0] + 1));
printf("%d\n", sizeof(*(&a[0] + 1)));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a[3]));
return 0;
}
解析:
int main()
{
int a[3][4] = { {1,2,3,4},{5,6,7,8},{8,9,0,1} };
printf("%zd\n", sizeof(a));
//出现了sizeof(数组名),计算的是整个数组的长度,结果是48
printf("%zd\n", sizeof(a[0][0]));
//a[0][0]代表的是第一行第一个元素0,结果是4
printf("%zd\n", sizeof(a[0]));
//a[0]是第一行的一维数组名,出现了sizeof(数组名),结果是16
printf("%zd\n", sizeof(a[0] + 1));
//a[0] + 1代表的是第一行第二个元素的地址,结果是4或8
printf("%zd\n", sizeof(*(a[0] + 1)));
//*(a[0] + 1)代表的是第一行第二个元素,结果是4
printf("%zd\n", sizeof(a + 1));
//a + 1代表的是第二行的一维数组的地址,结果是4或8
printf("%zd\n", sizeof(*(a + 1)));
//*(a + 1)代表的是第一行的一维数组解引用,得到的就是第一行的一维数组,结果是16
printf("%zd\n", sizeof(&a[0] + 1));
//&a[0]属于&(数组名)的情况,&a[0] + 1得到的就是第二行的一维数组的地址,结果是4或8
printf("%zd\n", sizeof(*(&a[0] + 1)));
//&a[0] + 1得到的就是第二行的一维数组的地址,*(&a[0] + 1)得到的就是第二行的一维数组,结果是16
printf("%zd\n", sizeof(*a));
//a代表第一行一维数组的地址,*a就是第一行一维数组,结果是16
printf("%zd\n", sizeof(a[3]));
//a[3]代表的是第三行一维数组后的一个数组,其中内容为随机值,结果为16
return 0;
}
运行结果:
📍大厂指针运算笔试题解析?
题目1:
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int* ptr = (int*)(&a + 1);
printf("%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
分析:
运行结果:
代码2:
注:在x86环境下
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p = (struct Test*)0x100000;
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
分析:
运行结果:
代码3:
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];
printf( "%d", p[0]);
return 0; }
分析:
运行结果:
代码4:
?
int main()
{
int a[5][5];
int(*p)[4];
p = a;
printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}
分析:
运行结果:
代码5:
?
int main()
{
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int* ptr1 = (int*)(&aa + 1);
int* ptr2 = (int*)(*(aa + 1));
printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
return 0;
}
分析:
运行结果:
?
代码6:
int main()
{
char* a[] = { "work","at","alibaba" };
char** pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
?分析:
?运行结果:
代码7:
int main()
{
char* c[] = { "ENTER","NEW","POINT","FIRST" };
char** cp[] = { c + 3,c + 2,c + 1,c };
char*** cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *-- * ++cpp + 3);
printf("%s\n", *cpp[-2] + 3);
printf("%s\n", cpp[-1][-1] + 1);
return 0;
}
?分析:
?“printf("%s\n", **++cpp)”执行后:
“printf("%s\n", *-- * ++cpp + 3)”执行后:
运行结果:
?
文章来源:https://blog.csdn.net/Dumpling527/article/details/134893312
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!