网站建设开发报价明细百度搜索引擎推广步骤
web/
2025/10/2 1:06:45/
文章来源:
网站建设开发报价明细,百度搜索引擎推广步骤,营销型网站开发 语言选择,做任务赚q币网站指针
为了后续一些安排打基础#xff0c;决定使用C/C作为算法主语言#xff0c;所以从这篇文章开始#xff0c;从指针开始总结
指针 - 指针进阶 - 字符串函数 - 自定义类型 - 动态内存管理 - 数据结构
还有C一些基础语法的回顾#xff08;基于算法…指针
为了后续一些安排打基础决定使用C/C作为算法主语言所以从这篇文章开始从指针开始总结
指针 - 指针进阶 - 字符串函数 - 自定义类型 - 动态内存管理 - 数据结构
还有C一些基础语法的回顾基于算法竞赛使用 文章目录 指针概念指针变量 指针和指针类型指针-整数解引用 野指针成因指针未初始化指针越界访问指针指向的空间释放 规避野指针 指针运算-整数指针-指针关系运算 指针和数组二级指针 概念 指针是内存中一个最小单元的编号也就是地址 平时口语中说的指针通常指的是指针变量是用来存放内存地址的变量
总的来说指针就是地址口语中说的指针通常指的是指针变量。
指针变量
我们可以通过取地址操作符取出变量的内存其实就是地址把地址可以存放到一个变量中这个变量就是指针变量
#include stdio.h
int main()
{int a 10; //在内存中开辟一块空间int *p a;//这里我们对变量a取出它的地址可以使用操作符。//a变量占用4个字节的空间这里是将a的4个字节的第一个字节的地址存放在p变量中p就是一个之指针变量。return 0;
}指针和指针类型
char *pc NULL;
int *pi NULL;
short *ps NULL;
long *pl NULL;
float *pf NULL;
double *pd NULL;指针±整数
#include stdio.h
//演示实例
int main()
{int n 10;char *pc (char*)n;int *pi n;printf(%p\n, n);printf(%p\n, pc);printf(%p\n, pc1);//打印指针 pc 向后移动一个单位1 字节后的内存地址使用 %p 格式说明符并换行printf(%p\n, pi);printf(%p\n, pi1);//打印指针 pi 向后移动一个单位4 字节后的内存地址使用 %p 格式说明符并换行。return 0;
}
//输出结果
00DDF7E8
00DDF7E8
00DDF7E9
00DDF7E8
00DDF7EC**总结**指针的类型决定了指针向前或者向后走一步有多大距离~
解引用
在C语言中指针解引用操作使用*符号来访问指针所指向的内存位置的值。也就是说使用*操作符可以获取指针所指向的内存位置的值或者可以修改该内存位置的值。
#include stdio.h
int main()
{int n 0x11223344;char *pc (char *)n;int *pi n;*pc 0; //重点在调试的过程中观察内存的变化。*pi 0; //重点在调试的过程中观察内存的变化。return 0;
}另外一个例子
#include stdio.hint main() {int num 10;int *ptr num;printf(Value of num: %d\n, num); // 输出Value of num: 10printf(Value of num using pointer: %d\n, *ptr); // 输出Value of num using pointer: 10*ptr 20; // 使用指针解引用操作修改指针所指向的内存位置的值printf(Updated value of num using pointer: %d\n, *ptr); // 输出Updated value of num using pointer: 20printf(Updated value of num: %d\n, num); // 输出Updated value of num: 20return 0;
}
//结果
Value of num: 10
Value of num using pointer: 10
Updated value of num using pointer: 20
Updated value of num: 20综上的例子我的理解就是指针的解引用操作就是可以修改那个被解引用对象或者变量的所在的内存的值
总结
指针的类型决定了对指针解引用的时候有多大的权限能操作几个字节。
比如 char* 的指针解引用就只能访问一个字节而 int* 的指针的解引用就能访问四个字节。
野指针
所谓的野指针就是指向无效内存地址的指针会导致不可预测的行为~
成因
指针未初始化
#include stdio.h
int main()
{ int *p;//局部变量指针未初始化默认为随机值*p 20;return 0;
}这段代码在声明了一个指针变量 p 后没有将其初始化为有效的内存地址而是直接对其进行解引用操作将值 20 存储到目标地址中。
要修复这个问题应该在使用指针之前先为其分配内存。可以使用 malloc() 函数来动态分配内存后面会更新或者将指针指向一个已有的变量或数组。以下是修复后的示例代码
#include stdio.h
int main()
{int *p malloc(sizeof(int)); // 分配内存用于存储 int 类型变量*p 20; // 解引用指针并为其赋值// 使用指针的值printf(Value: %d\n, *p);// 释放内存free(p);return 0;
}指针越界访问
#include stdio.h
int main()
{int arr[10] {0};int *p arr;int i 0;for(i0; i11; i){//当指针指向的范围超出数组arr的范围时p就是野指针*(p) i;}return 0;
}指针指向的空间释放
后面在动态内存管理的博客中会再总结一次~
一般这种指针被叫做悬空指针
当使用 free() 函数释放一个动态分配的内存块时该内存块被标记为可重新使用但指向该内存块的指针仍然保留着原来的地址。如果在释放内存之后继续使用该指针它就成为了一个指向已释放内存的野指针。
下面给个示例代码
#include stdio.h
#include stdlib.hint main()
{int *p;p malloc(sizeof(int));*p 10;free(p); // 释放了内存printf(Value: %d\n, *p); // 访问已释放内存的指针*p 20; // 修改已释放内存的指针return 0;
}在上述示例中我们首先使用 malloc() 分配了一个整型的内存块并将其赋值为 10。然后我们用 free() 函数释放了该内存块使得指针 p 成为了一个指向已释放内存的悬空指针。
接下来我们尝试访问该悬空指针的值并打印这个操作属于未定义行为可能会输出错误结果、崩溃或其他不可预测的行为。
最后我们尝试修改悬空指针的值为 20同样也是未定义行为可能会导致程序异常终止或产生其他意外结果。
为了避免这种问题我们应该在释放内存后将指针设置为 NULL并在使用指针之前检测其是否为 NULL。
#include stdio.h
#include stdlib.hint main()
{int *p;p malloc(sizeof(int));*p 10;free(p);p NULL; // 将指针设置为 NULLif (p ! NULL) {printf(Value: %d\n, *p); // 避免访问已释放内存的指针}p malloc(sizeof(int)); // 重新分配内存*p 20; // 修改重新分配的内存的值free(p);return 0;
}在修复后的示例中我们在释放内存后将指针 p 设置为 NULL。然后在使用指针之前我们先检查指针是否为 NULL以确保它指向有效的内存。我们还重新分配了内存并修改了相应的指针。
这个示例展示了正确处理指向已释放内存的指针的方式以避免悬空指针问题的发生。
规避野指针 指针初始化 小心指针越界 指针指向空间释放及时置NULL 避免返回局部变量的地址 指针使用之前检查有效性
指针运算
±整数
#include stdio.hint main() {int arr[] {10, 20, 30, 40, 50};int *ptr arr; // 指向数组的第一个元素// 使用指针的加法运算printf(Elements of array using pointer arithmetic:\n);for (int i 0; i 5; i) {printf(%d , *ptr);ptr; // 指针向后移动一个 int 大小的位置}printf(\n);// 使用指针的减法运算ptr arr[4]; // 指向数组的最后一个元素printf(Elements of array (reverse order) using pointer arithmetic:\n);for (int i 0; i 5; i) {printf(%d , *ptr);ptr--; // 指针向前移动一个 int 大小的位置}printf(\n);return 0;
}
//输出结果
Elements of array using pointer arithmetic:
10 20 30 40 50
Elements of array (reverse order) using pointer arithmetic:
50 40 30 20 10指针-指针
当两个指针相减时其结果是两个指针之间的距离以指针指向的类型大小为单位。这个结果是一个整数类型。
指针-指针的操作通常用于比较两个指针之间的距离或者计算数组中连续元素之间的距离。
#include stdio.hint main() {int arr[] {10, 20, 30, 40, 50};int *ptr1 arr[1]; // 指向数组的第二个元素int *ptr2 arr[4]; // 指向数组的最后一个元素// 计算指针之间的距离int diff ptr2 - ptr1;printf(Distance between ptr1 and ptr2: %d\n, diff);return 0;
}
//输出结果
Distance between ptr1 and ptr2: 3注意
两个指针必须指向同一个数组或同一块内存才能进行指针-指针的操作。
如果两个指针指向不同的数组或者一个指针指向数组的开始而另一个指针指向数组的结束则结果是无效的。 同时还可以使用指针-指针操作来比较两个指针的相对位置
#include stdio.hint main() {int arr[] {10, 20, 30, 40, 50};int *ptr1 arr[1]; // 指向数组的第二个元素int *ptr2 arr[3]; // 指向数组的第四个元素if (ptr1 ptr2) {printf(ptr1 is before ptr2\n);} else if (ptr1 ptr2) {printf(ptr1 is after ptr2\n);} else {printf(ptr1 and ptr2 are equal\n);}return 0;
}注意
仅当两个指针指向同一个数组或同一块内存时比较两个指针的相对位置才有意义。否则结果是未定义的。
关系运算
#include stdio.hint main() {int arr[] {10, 20, 30, 40, 50};int *ptr1 arr; // 指向数组的第一个元素int *ptr2 arr[2]; // 指向数组的第三个元素if (ptr1 ptr2) {printf(ptr1 is greater than ptr2\n);}if (ptr1 ptr2) {printf(ptr1 is less than ptr2\n);}if (ptr1 ptr2) {printf(ptr1 is greater than or equal to ptr2\n);}if (ptr1 ptr2) {printf(ptr1 is less than or equal to ptr2\n);}if (ptr1 ptr2) {printf(ptr1 is equal to ptr2\n);}if (ptr1 ! ptr2) {printf(ptr1 is not equal to ptr2\n);}return 0;
}指针和数组
#include stdio.h
int main()
{int arr[10] {1,2,3,4,5,6,7,8,9,0};printf(%p\n, arr);printf(%p\n, arr[0]);return 0;
}
00F3FBC8
00F3FBC8可见数组名和数组首元素的地址是一样的
int arr[10] {1,2,3,4,5,6,7,8,9,0};
int *p arr;//p存放的是数组首元素的地址既然可以把数组名当成地址存放到一个指针中我们使用指针来访问一个就成为可能。
例如
#include stdio.h
int main()
{int arr[10] {1,2,3,4,5,6,7,8,9,0};int *p arr;//p存放的是数组首元素的地址int sz sizeof(arr)/sizeof(arr[0]);for(i0; isz; i){printf(arr[%d] %p p%d %p\n, i, arr[i], i, pi);}return 0;
}
arr[0] 00AFF708 p0 00AFF708
arr[1] 00AFF70C p1 00AFF70C
arr[2] 00AFF710 p2 00AFF710
arr[3] 00AFF714 p3 00AFF714
arr[4] 00AFF718 p4 00AFF718
arr[5] 00AFF71C p5 00AFF71C
arr[6] 00AFF720 p6 00AFF720
arr[7] 00AFF724 p7 00AFF724
arr[8] 00AFF728 p8 00AFF728
arr[9] 00AFF72C p9 00AFF72C所以 pi 其实计算的是数组 arr 下标为i的地址。
那我们就可以直接通过指针来访问数组。
int main()
{int arr[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };int *p arr; //指针存放数组首元素的地址int sz sizeof(arr) / sizeof(arr[0]);int i 0;for (i 0; isz; i){printf(%d , *(p i));}return 0;
}二级指针
二级指针也称为指向指针的指针它是一种较为复杂的指针类型。通过使用二级指针我们可以操作指针的指针即通过一个指针间接引用另一个指针。
二级指针常用于需要在函数之间传递和修改指针的地址的情况它提供了更灵活的指针操作方式。
对于二级指针的运算有 *ppa 通过对ppa中的地址进行解引用这样找到的是 pa *ppa 其实访问的就是 pa int b 20;
*ppa b;//等价于 pa b;**ppa 先通过 *ppa 找到pa,然后对 pa 进行解引用操作*pa那找到的是 a . **ppa 30;
//等价于*pa 30;
//等价于a 30;再看一下下面代码
#include stdio.h
#include stdlib.hint main() {int val 42;int* ptr val; // 一级指针指向 val 的地址int** dptr ptr; // 二级指针指向 ptr 的地址printf(Value: %d\n, **dptr); // 通过二级指针访问 val 的值int* newVal (int*)malloc(sizeof(int)); // 动态分配内存*newVal 99; // 通过一级指针修改 newVal 的值*dptr newVal; // 通过二级指针修改 ptr 的值使其指向 newValprintf(Value: %d\n, **dptr); // 通过二级指针访问 newVal 的值free(*dptr); // 释放内存*dptr NULL; // 通过二级指针重置指针变量为 NULLreturn 0;
}在上述示例中我们首先声明了一个整型变量 val然后声明了一个一级指针 ptr该指针指向 val 的地址。然后我们声明了一个二级指针 dptr该指针指向 ptr 的地址。
在打印 **dptr 时我们使用两次解引用操作符 *可以间接访问 val 的值。
接下来我们使用 malloc 函数动态分配了一个新的整型变量并通过一级指针 newVal 修改了它的值。然后我们通过二级指针 dptr 修改了一级指针 ptr 的指向使其指向新分配的内存。
最后我们使用 free 函数释放了动态分配的内存并将指针变量重置为 NULL。 至此指针的初阶总结到此结束接下来会持续感谢~
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/85344.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!