<C> 指针
引入:
二进制中的三位 对应 八进制中的一位
二进制中的四位 对应 十六进制中的一位
例:001 010 011(2)→123(8)→0x53(53)
注:在位数不够的时候 前面补零去看
一.对一个变量我们可以进行哪些操作
1.写操作:a = 10;
2.读操作:用printf输出一个数的值
3.取地址操作:&a;
①内存→一个格子一个字节 例如:int a; 就是向系统申请了四个字节
一个格子就像一个房间 每个房间都有不同的编号 这个编号 就可以叫做内存的地址
②表示方法:取地址符 + 变量名称
如若想查看一个一个变量的地址 可以打为 printf("%p\n",&a); 来查看a的地址 返回的是首地址
③在32位中 地址是由8个16进制的数组成的 (00000000~FFFFFFFF)
注:每次在查看地址的时候 地址是变的 不是固定的
因为程序执行结束以后地址就会被收回 如果要再次执行就要重新分配空间
地址的名字是不再占用内存空间的
④地址偏移:
int型 4个字节 输出&a 和&a+1 结果差4
char 1个字节 输出&b 和&b+1 结果差1
结论:看指针所能操作的内存大小 看类型 与右边无关 看左边
⑤间接引用 *:指的是对内存空间进行操作
用法:* + 地址
二.指针
1.定义:本质是用来存储地址的变量
用法:变量类型 + * + 名(变量类型是需要存储地址的变量类型)
例如:
1 int* p = &a; 2 //p中存的是a的地址
注:p→&a 即*p = *&a = a的值 p中放的是a的地址 *p是a的值 指向空间的内容
2.sizeof():
sizeof不是一个函数 是一个操作符 是求变量或者类型的大小的(即占多少个字节)
例如:
1 #include<stdio.h> 2 int main() 3 { 4 int a = 10; 5 char b = 'a'; 6 int* p = &a; 7 char* pp = &b; 8 printf("%d\n",sizeof(p)); 9 printf("%d\n",sizeof(pp)); 10 }
上面这段程序在32位电脑中 运行的结果是4 4 在64位电脑中 结果应该是8 8
那么这就说明了:指针的大小与指向变量的类型是无关的
3.如何判断一个变量的类型呢?
去掉变量名 剩下的就是类型
4.如何判断一个指针所指向的类型?
去掉变量名 去掉一个* 所剩下的就是指针所指向的类型
5.多个指针可以指向同一空间(变量)因为他们的值是一样的
例题:
1 #include<stdio.h> 2 int main() 3 { 4 int a; 5 int* p1 = &a; 6 int* p2 = &a; 7 *p1 = 100; 8 printf("%d\n",*p2); 9 }
6.大端存储和小端存储:
大端存储通常在网络设备中 与小端相反 小端存储一般用于个人电脑 是低地址存在低字节中
字节序是从左到右的 从高到低
例题:int a = 0; char* p = &a;如何能让printf("%d\n",a)输出999999?
999999的二进制为 00000000 00001111 01000010 00111111(0 15 66 63)
1 #include<stdio.h> 2 int main() 3 { 4 int a = 0; 5 char* p = &a; 6 *p = 63; 7 p = p + 1; 8 *p = 66; 9 p = p + 1; 10 *p = 15; 11 printf("%d\n",a); 12 }
注:指针的大小与右边是无关的 与左边的类型有关
以下两种解决方式也都可以 在数组的地方 还可以有第四种解决方式
1 #include<stdio.h> 2 int main() 3 { 4 int a = 0; 5 char* p = &a; 6 *p++ = 63; 7 *p++ = 66; 8 *p++ = 15; 9 printf("%d\n",a); 10 }
1 #include<stdio.h> 2 int main() 3 { 4 int a = 0; 5 char* p = &a; 6 *p = 63; 7 *++p = 66; 8 *++p = 15; 9 printf("%d\n",a); 10 }
三.运算符优先级
这里放几道例题:a = 0; b = 1;
1.a = b++; //输出结果为 a = 1; b = 2;
2.a = ++b; //输出结果为 a = 2; b = 2;
3.a = ++b + ++b; //输出结果为a = 6; b = 3;(两边的b都变成了3)
4.a = b++ + b++; //输出结果为a = 2; b = 3;(这里的b是到下一行才变的)
5.
1 int n = 21; 2 printf("%d %d\n",n,n++);
输出结果为:22 21
这里就要提到一个叫函数栈的东西 它是符合栈的存储形式的
n先进栈 n++后进栈 先计算n++ 但此时n已经变成22 所以n输出为22
1 int n = 21; 2 printf("%d %d\n",--n,--n);
输出结果为:19 19
四.野指针
如果申请了一个指针 暂时不知道应该存谁的地址 那么就让它 = NULL
注:永远都不要操作不属于你的程序的内存空间
五.二级指针
这里就简单粗暴的放一道例题了解一下:
int a = 1; int b = 2; int* p = &a; int** pp = &p; 怎样才能使pp通过printf("%d\n",*p)输出b的值?
#include<stdio.h> int main() { int a = 1; int b = 2; int* p = &a; int** pp = &p; *pp = &b; printf("%d\n",*p); }
分析:*p = a
* pp = p = &a
** pp = a