先来简单的了解指针

可以说地址即是指针
通过指针(地址)能找到以它为地址的内存单元
存放于指针中的值都被当成地址处理
| 一个简单的指针 |
| int a=10; |
| int* p=&a; |
| int a = 1; |
| int *pa = &a; |
| char *pc = &a; |
| //取出地址一样 |
| printf("%p\n", pa); |
| printf("%p\n", pc); |
那既然输出的地址一样 那还区分char和int类型干嘛
| #include<stdio.h> |
| |
| int main() { |
| int a = 0; |
| int *pa = &a; |
| char *pc = &a; |
| printf("%p\n", pa); |
| printf("%p\n", pa + 1); |
| printf("%p\n", pc); |
| printf("%p\n", pc + 1); |
| } |

这样我们就很清楚的看到类型的作用:
即指针类型决定指针解引用能够访问空间的大小
不妨测试下:
| 指针变量的大小都一样 主要是访问空间的大小不同 |
| |
| |
| printf("%d\n", sizeof(char *)); |
| printf("%d\n", sizeof(int *)); |
| printf("%d\n", sizeof(float *)); |
常用的:
- int 4个字节
- char 1个字节
- double 8个字节
- float 8个字节
再看具体例子:
| int arr[10] = {0}; |
| |
| int *p = arr; |
| |
| |
| int i = 0; |
| for (i = 0; i < 10; ++i) { |
| *(p + i) = 1; |
| } |
| for (int i = 0; i < 10; ++i) { |
| printf("%p\n", arr[i]); |
| } |


可以看到改为char*后只能 向后修改10个字节 因为char类型的作用
野指针
简单来说就是指针指向位置是不可知的 就是瞎**乱指
三种情况:
| #include<stdio.h> |
| |
| int *fun(); |
| static int b; |
| int a; |
| float c; |
| |
| int main() { |
| |
| int *p; |
| printf("%d\n", a); |
| printf("%d\n", b); |
| printf("%f\n", c); |
| printf("%p\n", p); |
| |
| |
| int arr[10] = {0}; |
| int *pp = arr; |
| int i = 0; |
| for (i = 0; i < 12; ++i) { |
| *pp + 1; |
| } |
| |
| |
| int *ppp = fun(); |
| *ppp=20; |
| } |
| |
| int *fun() { |
| int a = 10; |
| return &a; |
| } |
如果要避免就对应上述三种情况避免 就是规范写法
指针的运算:
- 指针+-整数
- 指针-指针
- 指针的关系运算(比较大小)
这里穿插个知识 随着下标增大 对应地址也变大
| |
| int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; |
| int n = sizeof(arr) / sizeof(arr[0]); |
| int *p = arr; |
| for (int i = 0; i < n; ++i) { |
| printf("%d ", *p); |
| |
| *p += 1; |
| } |
| #include<stdio.h> |
| |
| #define value 5 |
| |
| int main() { |
| |
| float values[value]; |
| float *vp; |
| for (vp = &values[0]; vp < &values[value];) { |
| |
| *vp++ = 0; |
| } |
| printf("\n%d\n", *vp); |
| } |
| #include<stdio.h> |
| |
| int main() { |
| int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; |
| |
| printf("%d", &a[9] - &a[0]); |
| } |
规定比较只可与最后一个元素之后进行比较
指针和数组
还是要说到关于数组名首元素地址的问题:
| //关于元素首地址 |
| int arr[10] = {0}; |
| printf("%p\n", arr); |
| //加了4 |
| printf("%p\n", arr + 1); |
| |
| printf("%p\n", &arr[0]); |
| //加了4 |
| printf("%p\n", &arr[0] + 1); |
| |
| //&arr整个数组的地址 |
| printf("%p\n", &arr); |
| //加了40 跨过了一个数组 |
| printf("%p\n", &arr + 1); |
就两个例外: 1. &arr 取出整个数组地址 2.sizeof(arr) 表示整个数组大小
| |
| int x = 10, y = 20, c = 30; |
| int* ok[3]={&x,&y,&c}; |
| for (int i = 0; i < 3; ++i) { |
| printf("%d ",*(ok[i])); |
二级指针
| int* pa : *pa告诉是个指针 int 告诉指向对象类型为int |
| int a = 10; |
| int *p = &a; |
| int **p2 = &p; |
| printf("%d\n", **p2); |
| **p2 = 50; |
| printf("%d\n", a); |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?