既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
一.笔试题1 -指针与一维数组的关系-值
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1); //&a:取出整个数组的地址,&a+1:跳过一个数组
//&a的类型为:数组指针 int(*)[5] 所以要强转
//a为数组名,首元素地址,即为1的地址,+1,跳过一个元素,即为2的地址
printf( "%d,%d", *(a + 1), *(ptr - 1)); // 2 5
return 0;
}
图解:
二.笔试题2-指针与结构体
//这里告知结构体的大小是20个字节
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
int main()
{
p = 0x00100000;
//0x1-->对应的值就是1 相当于0x00000001
printf("%p\n", p + 0x1);//p为结构体指针,指向一个结构体,+1,跳过一个结构体,即跳过20个字节,
// 0x00100000+20 -> 0x00100020 错误, 要将20转化为16进制再加,或者将16进制0x00100000转化为10进制之后加上20,然后再转化为16进制
// 20-> 0X00000014
//所以最终结果为:0x00100014
printf("%p\n", (unsigned long)p + 0x1);//将p转化为长整形,+1,即为整形+1, 例如:500+1= 501,
//所以结果为: 0x00100001
printf("%p\n", (unsigned int*)p + 0x1);
//将p强转为无符号整形,+1跳过一个整形->跳过4个字节
//所以结果为:0x00100004
return 0;
}
注意坑点:整数+1 ->跳过一个字节 执行普通的加减运算
而整形指针+1 ->跳过四个字节
指针+1 的步长取决于指针指向的数据的类型
三.笔试题3-指针与一维数组的关系-址
int main()
{
int a[4] = { 1, 2, 3, 4 };
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)((int)a + 1);
printf( "%x,%x", ptr1[-1], *ptr2); // 4 2000000
return 0;
}
解析:
int *ptr1 = (int *)(&a + 1): 取出数组的地址+1,跳过一个数组,因为&a的类型为数组指针:int(*)[4] 类型不匹配,所以强转为int类型
prt1[-1]> *(ptr1+(-1))>*(ptr1-1)
int *ptr2 = (int *)((int)a + 1)
此时的a代表的首元素地址,地址值是一个常量,
整数+1:相当于跳过一个字节
所以应该画出数组的整体字节布局,注意要考虑小端存放,读取时倒着读取的问题
ptr2是整形指针,解引用向后访问4个字节
所以ptr2指向的是00 00 00 02这四个字节
要倒着拿:所以打印结果为:02000000
图解:
注意点:整形+1:加一个字节 如:500+1 = 501
整形指针+1:跳过(加)4个字节
四.笔试题4-指针与逗号表达式
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];
printf("%d ",p[0]); //1
return 0;
}
坑点:逗号表达式-结果为最后一个表达式的结果
图解:
所以相当于只初始化了前三个元素,后面的元素未初始化,默认为0
解析:
a[0] : 二维数组第一行的数组名,在这里是首元素地址,即第一行第一个元素的地址
p[0] >*(p+0)>*p
p是整形指针,解引用向后访问4个字节
五.笔试题5-指针与二维数组
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;
}
注意:p是数组指针,指向的数组有4个元素
指针-指针得到的是二者之间的元素个数
p[4] = *(p+4)
p[4][2] ==> *(*(p+4)+2)
图解:
&p[4][2]为小地址,&a[4][2]为大地址,小地址减大地址,所以最后结果为-4
-4:
原码:10000000 00000000 00000000 00000100
反码:11111111 11111111 11111111 11111011
补码:11111111 11111111 11111111 11111100
使用%p方式打印:打印的是-4对应的补码 1111 1111 1111 1111 1111 1111 1111 1100 ->结果为:FFFFFFFC
整数在内存中以补码方式存储,打印地址和打印无符号整数一样,都是打印内存中补码
使用%d方式打印:打印二进制补码对应的原码,=> -4
注意:a是二维数组,对应数组指针的类型为:int(*)[5],指向的是有5个元素的一维数组
而p是数组指针,指向的数组只有4个元素,所以会有警告
->可以写成 int(*p)[4] = (int(*)[4])a 消除警告
六.笔试题6-指针与二维数组
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)); // 5 10
return 0;
}
解析:
&aa:取出二维数组的地址 &aa+1:跳过二维数组
&二维数组应该使用数组指针接收,现在保存到整形指针,所以要强转。
aa:没有单独放在sizeof内部,没有&数组名,所以代表的是二维数组首元素地址,即二维数组第一行的地址
aa+1:跳过一行
*(aa+1) : 相当于拿到了第二行的数组名 等价于 aa[1]
图解:
七.笔试题7-指针与字符指针数组
#include <stdio.h>
int main()
{
char *a[] = {"work","at","alibaba"};
char**pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
解析:
a是数组,元素类型为:char* ,存放的是指向字符串的首字符地址
根据后面初始化的内容确定数组的大小
char** pa = a ; 此处的a是首元素地址,char**类型
--------
char**pa :一颗*说明pa是指针,另一颗*说明pa指向的类型是char*
pa+1:跳过char*
所以从字符a的地址向后打印,遇到\0即停止打印
打印结果为:at
图解:
八.笔试题9-指针与字符指针数组(难)
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
5p6c5YaN5Yqq5Yqb,size_20,color_FFFFFF,t_70,g_se,x_16)
八.笔试题9-指针与字符指针数组(难)
[外链图片转存中…(img-GP0Ysmf7-1715715806991)]
[外链图片转存中…(img-jLUFWLEq-1715715806992)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!