目录
数组名的理解 : 数组名就是首元素地址
但是有两个例外:
1. sizeof(数组名)这里的数组名表示整个数组的大小,sizeof(数组名)计算的是整个数组的大小,单位是字节
2. &数组名 这里的数组名表示整个数组 ,&数组名取出的是数组的地址
指针变量的大小和类型无关,不管什么类型的指针变量,大小都是4/8个字节
指针变量是用来存放地址的,地址存放需要多大空间,指针变量的大小就是几个字节
32位环境下,地址是32个二进制位,需要4个字节,所以指针变量的大小就是4个字节
64位环境下,地址是64个二进制位,需要8个字节,所以指针变量的大小就是8个字节
strlen函数,只有遇到 ' \0 ' 时才停止
sizeof ()是C语言中常用的运算符,可以计算操作数的大小
博主个人建议 : 自己先做一遍,看看哪个做错了,然后再看博主的解释
做对的题,自己想想因为什么得这个数,看看与博主的解释一样不
- #include
- int main()
- {
- int a[5] = { 1, 2, 3, 4, 5 };
- int* ptr = (int*)(&a + 1);
- printf("%d, %d", *(a + 1), *(ptr - 1));
- return 0;
- }
由上期重点可知:&数组名 , 这里的数组名表示整个数组 ,&数组名取出的是数组的地址
ptr = &a+1 ,ptr - 1在4和5之间所以*(ptr-1)是 5 ;
*(a+1) ,单独的数组名表示整个数组的大小,除此之外都是首元素地址,所以(a + 1)是首元素地址 + 1 也就是 2
- //由于还没学习结构体,这里告知结构体的大小是20个字节
- //X86 环境下演示
- struct Test
- {
- int Num;
- char* pcName;
- short sDate;
- char cha[2];
- short sBa[4];
- } * p;
- //假设p 的值为0x100000。 如下表表达式的值分别为多少?
- //已知,结构体Test类型的变量大小是20个字节
- //0x开头的数字是16进制的数字
- int main()
- {
- p = (struct Test*)0x100000;
- printf("%p\n", p + 0x1);
- printf("%p\n", (unsigned long)p + 0x1);
- printf("%p\n", (unsigned int*)p + 0x1);
-
- return 0;
- }
注意 :笔试题全套多到防不胜防,看到结果后,请问多少人掉进沟里了
这是一个结构体指针,在 x86 环境下它为20个字节
指针在进行加减法运算时,会跳过其所对应的字节数;例如int* a;在它进行+1后会跳过4个字节
题目中0x是表示十六进制............题目中 p 是一个20个字节的结构体指针,p+1也就是跳过20个字节也就是 0x100000+20(转换成十六进制是+14)所以最后结果为0x100014,关于进制转换不懂的可以看下面的进制的知识点科普
unsigned是类型强制转换,有多少人认为第二个printf输出的0x100004呢,掉进沟里了吧
此时的p不是指针,而是一个无符号长整型变量,+1只是加了一个字节,打印出来是0x100001
第三个printf,强制转换成了无符号整形指针,+1后其实是跳过了4个字节,打印出来是0x100004

二进制由 0 和 1 两个数字组成,使用时必须以0b或0B(不区分大小写)开头
例如: 0000 00011 十进制为 3 1*1+1*2
0000 00101 十进制为 5 1*1+1*4
八进制由 0~7 八个数字组成,使用时必须以0开头(注意是数字 0,不是字母 o)
例如:015 十进制为 13 1*8+5*1
-0101 十进制为 -65 -(1*64+1*1)
十六进制由数字 0~9、字母 A~F 或 a~f(不区分大小写)组成,使用时必须以0x或0X(不区分大小写)开头
例如: 0X2A; 十进制为 42 2*16+10
-0XA0 十进制为 -160 -(10*16+0)
- 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);
- return 0;
- }
注意 : %x是以十六进制的形式输出整数
ptr1 = &a + 1

第一个printf,这个是强制转换为 int* 形式,ptr1所在的位置是ptr [-1] ,以十六进制打印的话就是4
第二个printf 用到了数据在内存中的存储,如下
大端:是数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中。低地址-->>高数据 例如:手机
小端:是指数据的地位保存在内存的低地址中,数据的高位则保存在内存的高地址中。低地址-->>低数据 例如:电脑
a是数组首元素的地址,但是题目中强制转化成了int(整形变量),+1跳过了一个字节所以如上面图2把01跳了过去,上面解释了小端的存储形式,低地址就是低数据所以打印出来应该是20000000
![]()
- #include
- int main()
- {
- int a[3][2] = { (0, 1), (2, 3), (4, 5) };
- int* p;
- p = a[0];
- printf("%d", p[0]);//?
- return 0;
- }
注意:这个也是有坑的 ,二维数组里面定义的方式是小括号!!!!!
传递后面的数字,所以p[0]的值是1
打印的结果就是1
正确的是这么画的
- int main()
- {
- int a[5][5];
- int(*p)[4];//数组指针
- p = a;//类型合适吗?
- //a - int(*)[5]
- //p - int(*)[4]
-
- printf("%p, %d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
- //
- //%p是打印地址,认为内存中存储的补码就是地址
- //
- return 0;
- }

题目中说了a 一个五行五列的数组,*p是一个行省略四列的数组,,如上图, &p[4][2] - &a[4][2]他们两个相减等于-4,所以%d的值为-4,由于-4不是指针,打印他的十六进制形式就是FFFFFFFC
![]()
- 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;
- }

*(ptr1-1)也就是*(&aa+1-1)最后结果是10
*(ptr2-1)也就是(*(aa+1)-1最后结果是5

还有两道笔试题,在更新下一章的时候补充,记得点个关注,要不然容易找不到!!!!
下一章更新字符串函数,敬请期待
如果有解释的不对或者不清晰,麻烦大佬们海涵,如果可以烦请从评论区指出,我一定会加以修改,万分感谢
最后麻烦大佬们动一下发财的小手一键三连,万分感谢