【c语言】 指针详解 【图文+代码】

article/2025/8/29 7:34:23

指针

  • 前言
  • 一、指针是什么?
    • 1.1 认识指针
    • 1.2 变量
    • 1.3 变量放在哪?
    • 1.4 指针的本质
    • 1.5 解引用
  • 二、指针类型
    • 2.1指针有类型吗?
    • 2.2指针类型的意义是什么?
  • 三. 野指针
    • 3.1什么是野指针
    • 3.2野指针成因
      • 3.2.1指针未初始化
      • 3.2.2 指针越界访问
      • 3.2.3 指针指向的空间释放了
    • 3.3如何避免野指针
  • 四、 指针和数组
    • 4.1数组名是什么
    • 4.2数组和指针的关系
    • 4.3数组和指针的关系
  • 五、 二级指针
  • 六、 指针数组

前言

提示:编程的本质其实就是操控数据,而数据存放在内存中。因此,如果能更好地理解内存的模型,以及 C 如何管理内存,那么就引入了一个新的概念 “指针” ,大家都在书中看到过「指针存储的是变量的内存地址」这句话,但是什么是指针呢,下面我们开始直面了解指针


提示:以下是本篇文章正文内容,下面案例可供参考

一、指针是什么?

1.1 认识指针

在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。
在这里插入图片描述指针是个变量,存放内存单元的地址(编号)。说的形象一点就是指针就相当于一个门牌号 里面存的的是住户的编号

1.2 变量

   上面说指针是个变量 ,那么变量是什么。

有了内存,接下来我们需要考虑,int、double 这些变量是如何存储在 0、1 单元格的。
在 C 语言中我们会这样定义变量:

int a = 999;
char c = 'c';

当你写下一个变量定义的时候,实际上是向内存申请了一块空间来存放你的变量。我们都知道 int 类型占 4 个字节,并且在计算机中数字都是用补码表示的。
999换算成补码就是:0000 0011 1110 0111
这里有 4 个byte,所以需要四个单元格来存储:
在这里插入图片描述
当然,这样就引出了大端和小端。
像上面这种将高位字节放在内存低地址的方式叫做大端
反之,将低位字节放在内存低地址的方式就叫做小端:
在这里插入图片描述
上面只说明了 int 型的变量如何存储在内存,而 float、char 等类型实际上也是一样的,都需要先转换为补码。

对于多字节的变量类型,还需要按照大端或者小端的格式,依次将字节写入到内存单元。

1.3 变量放在哪?

上面我说,定义一个变量实际就是向计算机申请了一块内存来存放。
那如果我们要想知道变量到底放在哪了呢?

可以通过运算符&来取得变量实际的地址,这个值就是变量所占内存块的起始地址。

printf("%x", &b);

打印出来大概会是像这样的一串数字:0x7ffcad3b8f3c。

1.4 指针的本质

上面说,我们可以通过&符号获取变量的内存地址,那获取之后如何来表示这是一个地址,而不是一个普通的值呢?

也就是在 C 语言中如何表示地址这个概念呢?

对,就是指针,你可以这样:

#include <stdio.h>
int main()
{int a = 10;//在内存中开辟一块空间int *p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。//将a的地址存放在p变量中,p就是一个之指针变量。return 0;
}

大家都看到了 用int类型定义了一个指针p。
所以说到底,指针他的本质也就是一个变量,只不过是用来存放地址的变量。(存放在指针中的值都被当成地址处理)

就相当于刻在门牌上的号码,只能被当作门牌号处理了。

1.5 解引用

上面的问题,就是为了引出指针解引用的。

p中存储的是a变量的内存地址,那如何通过地址去获取a的值呢?

这个操作就叫做解引用,在 C 语言中通过运算符 *就可以拿到一个指针所指地址的内容了。
在这里插入图片描述

比如*p就能获得a的值。
形象的说
就相当于p里面是住户的门牌号(地址) *p就是你通过这个门牌号地址找到了里面的住户(内容)。

二、指针类型

2.1指针有类型吗?

指针的类型 我们都知道,变量有不同的类型,整形,浮点型等。那指针有没有类型呢? 准确的说:有的。

上面不是说过 指针是一个变量 变量有类型 那么指针肯定也有类型。

我们给指针变量相应的类型。

char  *pc = NULL;
int   *pi = NULL;
short *ps = NULL;
long  *pl = NULL;
float *pf = NULL;
double *pd = NULL;

这里可以看到,指针的定义方式是: type + * 。

         char* 类型的指针是为了存放 char 类型变量的地址。short* 类型的指针是为了存放 short 类型变量的地址。int* 类型的指针是为了存放int 类型变量的地址。

2.2指针类型的意义是什么?

我们先看一段代码
在这里插入图片描述
可以看出 &n pc pi所得到的地址相同
&n 本来就是取n 的地址 而pc pi 是指针 保存了n的地址 有人会疑问说不是一个是char类型 一个是int类型 怎么会一样呢?

在这里插入图片描述
那么pc+1 和 pi+1 为什么会不同 这就和指针的类型有关了 pc是char*

类型, +1 相当于加一个char类型字节大小 , 为一个字节, 而pi是int*类型 ,+1相当于加一个整形类型字节大小, 为4个字节。所以会有所不同 , 这也就是为什么指针会有不同的类型了。

指针的类型决定了指针向前或向后走一步有多大。


三. 野指针

3.1什么是野指针

野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

3.2野指针成因

3.2.1指针未初始化

#include <stdio.h>
int main()
{ int *p;//局部变量指针未初始化,默认为随机值*p = 20;return 0;
}

没有初始化造成了他的随机 不确定性 成了野指针。

3.2.2 指针越界访问

#include <stdio.h>
int main()
{int arr[10] = {0};int *p = arr;int i = 0;for(i=0; i<=11; i++){//当指针指向的范围超出数组arr的范围时,p就是野指针*(p++) = i;}return 0;}

指针越界了 指向了不属于自己的,也会造成它的随机 不确定性 从而成为野指针

3.2.3 指针指向的空间释放了

这个是大家最容易出错的也最容易忽略的一个问题。比如

int main()
{
vector<int> v={ 1, 2, 3, 4 };
auto it = v.begin();
while (it != v.end())
{
if (*it % 2 == 0)
v.erase(it);  //迭代器失效了 因为将2删除后 就不能在对其进行迭代
++it;
}
return 0;
}

原因就是指针指向那个空间时 将其删除后,没有给指针重新赋值,导致指针指向的位置又变成了未知的 随机的 成为野指针 从而造成程序崩溃。这个后边动态内存开辟在详细说这种情况。

3.3如何避免野指针

1.指针初始化
2.小心指针越界
3.指针所指空间释放了即设置NULL
4.指针使用之前检查其有效性 (断言)

四、 指针和数组

4.1数组名是什么

#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;
}

结果如下
在这里插入图片描述
我们会发现结果相同 我们就可以得出结论

数组名表示的是数组首元素的地址。
这样的话我们就可以这样写代码

int arr[10] = {1,2,3,4,5,6,7,8,9,0};
int *p=arr;//p存放的是数组首元素的地址

4.2数组和指针的关系

数组是 C 自带的基本数据结构,彻底理解数组及其用法是开发高效应用程序的基础。

int array[10] = {10, 9, 8, 7};
printf("%d\n", *array);  // 	输出 10
printf("%d\n", array[0]);  // 输出 10printf("%d\n", array[1]);  // 输出 9
printf("%d\n", *(array+1)); // 输出 9int *p = array;
printf("%d\n", *p);  // 	输出 10
printf("%d\n", p[0]);  // 输出 10printf("%d\n", p[1]);  // 输出 9
printf("%d\n", *(p+1)); // 输出 9
    第 0 个元素的地址称为数组的首地址,数组名实际就是指向数组首地址,当我们通过array[1]或者*(array + 1)去访问数组元素的时候。实际上可以看做 address[offset],address为起始地址,offset为偏移量,但是注意这里的偏移量offset不是直接和 address相加,而是要乘以数组类型所占字节数。也就是: address + sizeof(int) * offset   就是和指针的类型大小有关了。

特别要注意是:

尽管数组名字有时候可以当做指针来用,但数组的名字不是指针。  

比如

printf("%u", sizeof(array));
printf("%u", sizeof(p));

结果如下
在这里插入图片描述
一个是数组的大小 一个是指针的大小

     第一个输出 40,因为 array包含有 10 个int类型的元素,而第二个在 32 位机器上输出 4,也就是指针的长度。

另外说一下 指针就像门牌 它是一个标准的 在32位机器上永远就是 4

4.3数组和指针的关系

不要认为二维数组在内存中就是按行、列这样二维存储的,实际上,它在存储上和一维数组没有本质区别,举个例子:

int array[3][3] = {{1, 23}, {4, 56}{7, 8, 9}};
array[1][2] = 6;

或许你以为在内存中 array数组会像一个二维矩阵:

1		2		3
4		5		6
7		8		9

其实是这个样子哒

1	2	3	4	5	6	7	8	9

和一维数组没有什么区别,都是一维线性排列。
去访问的时候,编译器会怎么去计算我们真正所访问元素的地址呢?
假设数组定义是这样的:

   int array[n][m]  定义几行几列
访问: array[a][b]  比如要找array[1][2]
那么被访问元素地址的计算方式就是: array + (m * a + b)

这个就是二维数组在内存中的本质,其实和一维数组是一样的,只是语法将其包装成一个二维的样子。


五、 二级指针

在这里插入图片描述

*ppa 通过对ppa中的地址进行解引用,这样找到的是 pa

int b = 20;
*ppa = &b;//等价于 pa = &b;

**ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作:*pa,那找到的就是a

**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;

六、 指针数组

  指针数组是 “指针” 还是“数组”答案 当然是数组 

下面用图形的方式看一下 就会一目了然。

int arr1[5];
char arr2[5]
int *arr3[5]

在这里插入图片描述

arr3是一个数组,有五个元素,每个元素是一个整形指针

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

相关文章

【初阶】C语言指针详解——指针必备的7大知识点

文章目录 前言一、指针是什么&#x1f351;1、浅谈指针&#x1f351;2、内存&#x1f351;3、指针变量 二、指针和指针类型&#x1f351;1、指针类型&#x1f351;2、指针-整数&#x1f351;3、指针的解引用 三、野指针&#x1f351;1、野指针成因&#x1f333;(1) 指针未初始化…

详解C语言指针

文章目录 1.字符指针2.指针数组3.数组指针3.1 数组指针的定义3.2 &数组名和数组名的区别3.3 数组指针的使用 4.数组参数&#xff0c;指针参数4.1 一维数组传参4.2 二维数组传参4.3 一级指针传参4.4 二级指针传参 5.函数指针6.函数指针数组7.指向函数指针数组的指针8.回调函…

C语言——指针(入门详解)

文章目录 1.什么是指针&#xff1f;1.1.理解指针的两个要点&#xff1a;1.2.指针变量&#xff1a;1.3.内存是如何编址&#xff1f; 2.指针和指针类型2.1指针的创建与初始化2.2.指针类型 3.野指针3.1.什么视野指针&#xff1f;3.2.野指针成因3.3.规避野指针 4.指针运算4.1.指针-…

c语言指针用法详解,通俗易懂超详细!

文章转自&#xff1a;无际单片机 大家好&#xff0c;我是无际。 今天给大家来讲解一下指针。 我会由浅到深&#xff0c;最后结合实际应用讲解&#xff0c;让大家学会指针的同时&#xff0c;知道大佬们都用指针来干嘛&#xff01; 长文预警&#xff01;全文大约5200多字&#xf…

C语言指针详解(超级详细)

C语言指针精解 前言 这不是我第一次写关于C指针的文章了&#xff0c;只是因为指针对于C来说太重要&#xff0c;而且随着自己编程经历越多&#xff0c;对指针的理解越多&#xff0c;因此有了本文。然而&#xff0c;想要全面理解指针&#xff0c;除了要对C语言有熟练的掌握外&…

C语言中的指针详解

1. 什么是指针 C语言中指针是一种数据类型,指针是存放数据的内存单元地址。 计算机系统的内存拥有大量的存储单元,每个存储单元的大小为1字节,为了便于管理,必须为每个存储单元编号,该编号就是存储单元的“地址”,每个存储单元拥有一个唯一的地址。 指针变量除了可以存…

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

目录 1.什么是指针&#xff1f; 1.1概念 1.2指针的大小 ​ 1.3指针类型的作用 2.野指针 2.1野指针产生的原因 2.2 如何规避野指针 3.指针运算 3.1指针-整数 3.2指针-指针 3.3 指针的关系运算 4. 二级指针 5. 数组名 *6.指针数组和数组指针 6.1指针数组 *6.…

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;足够多的已标注样例是获得高精度分类器的…