C语言——指针详解(必收藏)

article/2025/8/29 10:10:10

目录

1.什么是指针?

1.1概念

1.2指针的大小

​ 1.3指针类型的作用

2.野指针 

2.1野指针产生的原因

2.2 如何规避野指针

3.指针运算 

3.1指针+-整数

3.2指针-指针

3.3 指针的关系运算 

4. 二级指针

5. 数组名

*6.指针数组和数组指针 

6.1指针数组

*6.2数组指针 

 6.3举例区别含义

7.数组参数和指针参数

7.1数组参数

7.2指针传参

8.函数指针 

9.函数指针数组

9.1指向函数指针数组的指针

*10.回调函数

1.什么是指针?

1.1概念

简单的来说,指针就是地址。我们口头上说的指针其实指的是指针变量。指针变量就是一个存放地址的变量。

1.2指针的大小

 指针在32位机器下是4个字节,在64位机器下是8个字节。注:(指针的大小与类型无关)

 

 1.3指针类型的作用

上面涉及到指针的大小与指针类型无关,那么指针类型的作用是什么呢?

指针解引用访问,使用的访问权限是多少    话不多说,上图!

当一个int* 的指针+1,跳过4个字节;当一个char* 的指针+1,跳过1个字节。

同理,对于(指针+-整数)类的题也是如上的原理。

2.野指针 

野指针顾名思义,指针指向的位置不可知,就像没有主人的流浪狗。

2.1野指针产生的原因

  1. 指针未被初始化

  2. 指针越界访问

  3. 指针指向的空间释放

对于前两点比较好理解,下面对第三点进行解释:

int* test( )
{int a = 5;return &a;
}
int main()
{int* p = test();*p = 10;return 0;
}

变量a的地址只在test()函数内有效,当把a的地址传给指针p时,因为出了test函数,变量a的空间地址释放,导致p变成了野指针。

2.2 如何规避野指针

  1. 小心越界
  2. 及时把指针赋成空指针
  3. 避免返回局部变量的地址
  4. 使用指针前检查有效性

3.指针运算 

3.1指针+-整数

此部分内容跟指针类型那部分一致

3.2指针-指针

指针-指针的绝对值指的是两个指针之间元素的个数。

前提:两个指针必须指向同一空间

例如:&arr[9]-&arr[0] 

下面举个例子实现my_strlen函数

int my_strlen(char str[])
{char* p = str;int count = 0;while (*p != '\0'){p++;count++;}return count;
}int main()
{char arr[] = "abcdef";printf("%d\n",my_strlen(arr));return 0;
}

3.3 指针的关系运算 

此部分内容很简单,指针与指针之间比较大小就是指针的关系运算。

例如:定义int* p1,数组int arr[5],p1>&arr[5]。

但是要遵循一个标准:允许指针指向数组元素和指针指向数组最后一个元素后面的位置进行比较,不允许指针指向数组元素与指针指向数组第一个位置的前面进行比较。

4. 二级指针

二级指针就是存放指针地址的指针变量。就像有三个抽屉第一个抽屉的钥匙放在第二个抽屉,第二个抽屉的钥匙放在第三个抽屉。

例如:int a=10;int* p1=&a;int** p2=&p1;

对int* * 做解释:第一个*号代表指针指向的类型是int*的,第二个*代表这个是指针。

5. 数组名

数组名大家都很熟悉,但要区分以下几种情况:

  1. sizeof(arr):表示的是整个数组的大小。
  2. &arr: 表示整个数组,取出的是整个数组的大小。

其他情况数组名都表示数组首元素地址。

*6.指针数组和数组指针 

6.1指针数组

  1. 定义:存放指针的数组(int* arr[])。我们知道有整型类型的数组int arr[],还有字符类型的数组char arr[],指针数组就是指针类型的数组。

  2. 以下举个例:

int main()
{int a = 0;int b = 1;int* p1 = &a;int* p2 = &b;int* arr[] = { p1,p2 };//指针数组int* arr[] = { &a,&b };//指针数组return 0;
}

*6.2数组指针 

  1. 定义: 指向数组的指针int (*)[]。
  2. 应用:遍历整个二维数组
void my_print(int(*p)[5], int x, int y)
{int i = 0;for (i = 0; i < x; i++){int j = 0;for (j = 0; j < y; j++){printf("%d ", *(*(p + i) + j));//printf("%d ", p[i][j]);相似的写法}printf("\n");}
}int main()
{int arr1[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };my_print(arr1, 3, 5);return 0;
}

 6.3举例区别含义

  • int arr[5]               //名为arr的数组,数组里有5个元素,每个元素是int
  • int* p1[5]              //指针数组,数组里有5个元素,每个元素是int*
  • int (*p2)[5]            //数组指针,一个指向数组(里面有五个元素,每个元素是int)的指                                  针
  • int (*p3[5])[5]        //p3[5]是一个有5个元素的数组,数组里每个元素是int(*)[5]

7.数组参数和指针参数

7.1数组参数

  • 一维数组传参: int arr[10](形参部分数组大小可以不写)、int* arr
  • 二维数组传参: int arr[3][5]、int arr[][5](行可以省略,列不能)、int (*arr)[5]                                          不能直接传数组名,二维数组的首地址是第一行元素的首地址

7.2指针传参

  • 一级指针传参:int* p
  • 二级指针传参:int** p

8.函数指针 

  1. 定义:指向函数的指针int (*pf) (int,int),pf函数返回的类型是int (*)(int,int)
  2. 对于函数来说如:Add和&Add,意义和值都一样。这一定要区别于数组。
  3. 特别的,当要调用函数时,定义一个pf的函数指针指向函数。那么int ret=(*pf)(2,3)和int ret=pf (2,3)等价。

 **对下面代码的理解:

(*(void(*)())0)()                            //   将0处强制类型转换为函数指针类型,再对0地址                                                                       进行调用

void(*signal(int,void(*)(int)))(int)        //这是函数的声明,singal是一个函数,传进去两个                                                                    参数的类型是int和void(*)(int),signal函数的返回值                                                                  类型是void(*)(int)。

9.函数指针数组

  1. 定义:存放函数指针类型元素的数组
  2. 应用:实现计算器
#include<stdio.h>int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}void menu()
{printf("****************\n");printf("* 1.Add  2.Sub *\n");printf("* 3.Mul  4.Div *\n");printf("***  0.exit  ***\n");printf("****************\n");
}int main()
{menu();int input = 0;printf("请选择:");scanf("%d",&input);int ret = 0;//转移表int(*pfarr[])(int, int) = { 0,Add,Sub,Mul,Div };do{if (input == 0){printf("退出\n");break;}else if (input >= 1 && input <= 4){int x = 0;int y = 0;printf("请输入两个操作数:");scanf("%d%d",&x,&y);ret = pfarr[input](x,y);printf("结果是%d\n",ret);break;}else{printf("选择错误!");}} while (input);return 0;
}

9.1指向函数指针数组的指针

1.定义:int (*(*parr)[4])(int  int)=&parr

*10.回调函数

  • qsort()函数: 是一个库函数,基于快速排序算法实现的一个排序的函数。优点是,任意类型的数据都能排序
  • qsort()函数的形参定义:

void qsort(void* base(起始地址),size_t num(元素个数),size_t width(一个元素的字节长度),int (*cmp)(const void* e1,const void* e2)(自定义比较函数))

  • qsort()函数应用:模拟计算器,排序结构体
//模拟计算器,对上面的代码进行优化
#include<stdio.h>void print(int* str, int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d ", str[i]);}printf("\n");
}void swap(char* e1, char* e2, int width)
{int temp = 0;int i = 0;for (i = 0; i < width; i++){temp = *e1;*e1 = *e2;*e2 = temp;e1++;e2++;}
}int cmp(const void* e1, const void* e2)
{return (*(int*)e1 - *(int*)e2);//e1>e2-> >0;e1=e2-> 0;e1<e2-> <0
}int bubble_sort(void* base, int num, int width, int(*cmp)(const int* e1, const int* e2))
{int i = 0;int j = 0;for (i = 0; i < num - 1; i++){for (j = 0; j < num - 1 - i; j++){if (cmp((char*)base + j * width, (char*)base + (j + 1) * width)>0){swap((char*)base + j * width, (char*)base + (j + 1) * width, width);}}}
}int main()
{int arr[] = { 9,8,7,3,5,4,2,1,6,0 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz, sizeof(arr[0]), cmp);print(arr, sz);return 0;
}
//排序结构体
#include<stdio.h>
struct Student
{char name[20];int age;double score;
};int cmp_name(const void* e1, const void* e2)
{return strcmp(((struct Student*)e1)->name, ((struct Student*)e2)->name);
}int main()
{struct Student arr[] = { {"zhang",17,80.6},{"wang",20,85.2},{"li",19,92.0} };int sz = sizeof (arr) / sizeof (arr[0]);qsort(arr,sz,sizeof (arr[0]),cmp_name);return 0;
}


http://chatgpt.dhexx.cn/article/xQYTMCem.shtml

相关文章

C语言指针详解

一、什么是指针 C语言里&#xff0c;变量存放在内存中&#xff0c;而内存其实就是一组有序字节组成的数组&#xff0c;每个字节有唯一的内存地址。CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位。这里&#xff0c;数据对象是指存储在内存中的一个指定数据类…

C语言之指针详解

文章目录 1 指针1.1 简介1.2 什么是指针1.2.1 定义1.2.2 指针表示1.2.3 为什么*p&a不正确 1.3 使用指针1.3.1 简单使用1.3.2 NULL 指针1.3.3 指针算术运算1.3.3.1 定义1.3.3.2 遍历数组&#xff1a;递增一个指针1.3.3.3 遍历数组&#xff1a;递减一个指针1.3.3.4 指针的比较…

c语言—指针详解

文章目录 一、指针是什么二、指针和指针变量1.左值与右值2.两者的区别 三、指针和指针类型1.定义指针2.大小端3.指针的解引用 四、野指针野指针成因如何规避野指针 五、指针运算1.指针- 整数2.指针-指针3.指针的关系运算 六、指针和数组七、二级指针八、指针数组和数组指针1.指…

机器学习主动学习和半监督学习

一、主动学习&#xff08;active learning&#xff09; 学习器能够主动选择包含信息量大的未标注的样例并将其交由专家进行标注&#xff0c;然后置入训练集进行训练&#xff0c;从而在训练集较小的情况下获得较高的分类正确率&#xff0c;这样可以有效的降低构建高性能分类器的…

active learning主动学习

active learning 是半监督式的机器学习的一种&#xff0c;这种机器学习算法能够交互式地查询用户或者信息源&#xff0c;从而对于一个新的数据样例得到可人的输出。在统计学文献中&#xff0c;它有时也被称为最佳实验设计。 在这样的一种情形下&#xff1a;无标签的数据量很大…

深度主动学习综述2020

A Survey of Deep Active Learning 中文版仅作参考&#xff0c;以正式的pdf版为主。 https://arxiv.org/pdf/2009.00236.pdf 西北大学等最新《深度主动学习》全面综述论文&#xff0c;30页pdf abstract 主动学习试图通过标记最少量的样本使得模型的性能收益最大化。而深度学习…

每日一学-- 主动学习(active learning)

1. 在机器学习中&#xff0c;有监督学习、半监督学习、无监督学习。 在使用监督学习时&#xff0c;模型在标注的数据中学习信息&#xff0c;而存在的问题就是有大量的数据需要标注&#xff0c;非常费时费力。so主动学习为我们提供了方法&#xff0c;通过一定的算法找出最有用的…

一张图展示被动学习与主动学习的效率差距

一张图展示被动学习与主动学习的效率差距 起因一张图 起因 由于工作原因。最近的一段时间&#xff0c;又回到了大量的学习实践当中。之前的主观感受是&#xff0c;通过文字语音视频结合的多渠道信息获取方式学到的东西&#xff0c;记忆会比自己只是看文字&#xff0c;读文字&a…

深度学习 主动学习(Active Learning)概述、策略和不确定性度量

文章目录 主动学习概念策略基于数据流的主动学习方法基于数据池的主动学习方法基于查询的主动学习方法 不确定性度量 参考 主动学习 概念 主动学习是指对需要标记的数据进行优先排序的过程&#xff0c;这样可以确定哪些数据对训练监督模型产生最大的影响。主动学习不是一次为…

主动学习-综述

主动学习是机器学习&#xff08;更普遍的说是人工智能&#xff09;的一个子领域&#xff0c;在统计学领域也叫查询学习、最优实验设计”(Active learning (sometimes called “query learning” or “optimal experimental design” in the statistics literature) is a subfie…

深度学习--主动学习

主动学习简介 主动学习是指对需要标记的数据进行优先排序的过程&#xff0c;这样可以确定哪些数据对训练监督模型产生最大的影响。主动学习是一种学习算法可以交互式查询用户(teacher 或 oracle)&#xff0c;用真实标签标注新数据点的策略。主动学习的过程也被称为优化实验设计…

机器学习/深度学习几种典型学习范式|主动学习

机器学习/深度学习几种典型学习范式|主动学习 主动学习&#xff08;Active Learning,AL&#xff09;&#xff1a;Introduction主动学习的例子 应用场景成员查询合成流式选择抽样基于池的主动学习 查询策略框架不确定性抽样Uncertainty Sampling基于委员会的查询Query-By-Commit…

机器学习中的主动学习(Active Learning)

最近在做主动学习相关的东西&#xff0c;随着深入了解和学习对于某些东西有一些模糊&#xff0c;先将所见所感整理如下&#xff0c;如有不正确之处希望大佬能够指正&#xff1a; 1.主动学习 1.1关键问题 对于监督学习模型&#xff0c;足够多的已标注样例是获得高精度分类器的…

主动学习数据标注

active learning与passive(supervised) learning最大的不同是其不需要大量的专家标注样本训练模型。 主动学习是利用少量标注样本&#xff0c;然后由模型&#xff08;Learner&#xff09;主动选择hard sample返回给用户或专家&#xff08;Oracle&#xff09;打标签&#xff0c;…

浅谈主动学习(Active Learning)

1背景概述 在机器学习领域有很多学习模式&#xff0c;比方说监督学习、半监督学习、强化学习、无监督学习等。平时大家接触比较多的一般都是监督学习&#xff0c;在监督学习里面&#xff0c;比方说要做个人和鱼的图像分类模型&#xff0c;假设有200张图片&#xff0c;那就需要把…

深度主动学习综述(Deep Active Learning)

原文 Abstract 主动学习试图通过标记最少量的样本使得模型的性能收益最大化。而深度学习则对数据比较贪婪&#xff0c;需要大量的数据供给来优化海量的参数&#xff0c;从而使得模型学会如何提取高质量的特征。近年来&#xff0c;由于互联网技术的快速发展&#xff0c;使得我…

AL-实体抽取主动学习调研

实体抽取主动学习调研 文章目录 实体抽取主动学习调研资料前言相关文献阅读一、主动学习与自学习的中文命名实体识别算法流程图 二、DEEP ACTIVE LEARNING FOR NAMED ENTITYRECOGNITION三、Visual Active Learning for Labeling: A Case for Soundscape四、Interactive visual …

《异常检测——从经典算法到深度学习》15 通过无监督和主动学习进行实用的白盒异常检测

《异常检测——从经典算法到深度学习》 0 概论1 基于隔离森林的异常检测算法 2 基于LOF的异常检测算法3 基于One-Class SVM的异常检测算法4 基于高斯概率密度异常检测算法5 Opprentice——异常检测经典算法最终篇6 基于重构概率的 VAE 异常检测7 基于条件VAE异常检测8 Donut: …

主动学习简单教程及代码示例

本文是这篇文章的&#xff08;翻译&#xff09;简化版。 本文代码地址 已经不止一次有人说代码地址打不开&#xff0c;但是每次我都打得开。。这里放个阿里云的地址吧Active_Learning_Tutorial.ipynb。需要的去阿里云下载文件就行了。 建议直接看代码地址&#xff08;代码地…

主动学习研究现状

主动学习研究现状 一. 传统查询策略&#xff08;Query Strategy&#xff09;二. 在图像分类的应用三. 在目标检测的研究3.1.《Localization-Aware Active Learning for Object Detection 》(ACCV, 2018)3.2. 《Active Learning for Deep Object Detection via Probabilistic Mo…