C语言中指针的详解

article/2025/8/29 7:10:03

文章目录

  • 前提
  • 一.指针基础
    • 1.1 变量指针
    • 1.2 数据指针
    • 1.3 指针的本质
    • 1.4 指针数组
    • 1.5 指针的移动
    • 1.5 Scanf函数的解释
  • 二.指针的进阶玩法
    • 2.1 二维指针
    • 2.2 结构体指针
  • 结语

前提

指针,是C语言中的一个重要概念及其特点,也是掌握C语言比较困难的部分。指针也就是内存地址,指针变量是用来存放内存地址的变量,在同一CPU构架下,不同类型的指针变量所占用的存储单元长度是相同的,而存放数据的变量因数据的类型不同,所占用的存储空间长度也不同。有了指针以后,不仅可以对数据本身,也可以对存储数据的变量地址进行操作
指针描述了数据在内存中的位置,标示了一个占据存储空间的实体,在这一段空间起始位置的相对距离值。在 C/C++语言中,指针一般被认为是指针变量,指针变量的内容存储的是其指向的对象的首地址,指向的对象可以是变量(指针变量也是变量),数组,函数等占据存储空间的实体。

一.指针基础

1.1 变量指针

//首先我们声明一个变量
int a = 10;	//声明一个指针并指向该变量的地址	
int* b = &a;	printf("%d\n", *b);

运行结果:10

1.2 数据指针

//首先我们声明一个数组变量
int c[10] = { 0,1,2,3,4,5,6,7,8,9 };		
printf("c的地址:%p\n", c);	
printf("c[0]的地址:%p\n", &c[0]);

运行结果:两个一样
Why? 数组本质为内存空间上连续的空间,而作为数组的地址,其实为首元素的地址,而对于数组,数组名称其实就是个指针(重点)
然后我们创建数组指针

int* d=c
printf("d[9]的值为:%d\n",*(d+9));
//另一种写法printf("d[9]的值为:%d\n",d[9]);

运行结果:9

1.3 指针的本质

通过1.0和1.1的指示我们突然发现,整数的指针和整数数组的指针居然是同个类型!
事实上确实是一个东西,指针为指向变量地址的类型,所以对于指针来说是不需要类型的,但是为了程序规范性,增加了类型说法
下面使用无类型指针输出a的值(10)

void* p = &a;
printf("void指针的值:%d\n", *(int*)p);
//对比b指针变量
printf("这是b的值:%p\n", b);
printf("这是p的值:%p\n", p);

在这里插入图片描述
上述结果可以完全表明,指针变量储存的是地址,而且是单一变量的地址
接下来可以解释数组和数为啥指针就是同一个类型了
回到1.2所述 单个数占了1个空间(这里不提占用内存),而数组占了n个空间,而指针指向的都是首地址,而对于单个数来说
首地址就是数所在的地址,而对于数组来说,首地址就是头元素所在的地址
1.2解释了数组地址就是数组名本身,所以数组指针就是数组本身了,所以有下面这种写法

printf("直接使用数组名获取索引3的元素:%d\n", c[3]);
printf("使用指向c的指针获取索引3的元素:%d\n", d[3]);

在这里插入图片描述
但是数组和指针数组还是有一定的区别

1.4 指针数组

/如果我们把指针看作一个变量,那么类比整数类型,我们一定可以声明一个指向指针的指针

int g = 50;
int* h = &g;
int** i = &h;
//输出一下
printf("h的值:%p\n", h);
printf("i的值:%p\n", *i);
//实验证明这是可行的,那我们尝试做一个数组
int j[5] = { 9,8,7,6,5 };
int* k[5] = { &j[0],&j[1],&j[2],&j[3],&j[4] };
int** l = k;
printf("k[1]的值:%p,对应的整数的值:%d\n", k[1], *k[1]);
printf("l获取k1的值:%p,对应的整数的值:%d\n", *(l + 1), **(l + 1));

在这里插入图片描述
这就是指针数组,把指针当作一个变量看,指针也可以做数组

1.5 指针的移动

对于数组指针获取元素,上面展示了可以通过"变量名[索引]"的方式获取,当然也可以通过移动指针位置来获取

int* m = (int*)malloc(10 * sizeof(int));
for (int i = 0; i < 10; ++i)*(m++) = i;

指针移动到了分配内存的最后一块
“变量名[索引]“的方式表明了是以当前指针为数组头,偏移索引个单位为方法获取元素的方式,索引获取第8个元素
错误写法 printf(”%d”,m[8]);
正确写法

printf("%d\n", *(m - 2));

在这里插入图片描述
所以释放的时候要释放头指针,所以要回到头指针

for (int i = 0; i < 10; ++i)(--m);
free(m);

所以实际操作的情况下尽量不要去移动指针

int* n = (int*)malloc(10 * sizeof(int));
for (int i = 0; i < 10; ++i)*(n + i) = i;
printf("%d\n", *(n + 8));
free(n);

在这里插入图片描述

1.5 Scanf函数的解释

scanf函数为获取变量地址函数
首先我们看一下scanf函数的定义
scanf函数有一个格式符参数和一个可变参数
可变参数类型为指针!!!!

char o;

第一种直接写法
scanf(“%c”, &o);
printf(“输出的字符:%c\n”, o);
同理
用指针获取

char* q = &o;
scanf("%c", q);
printf("通过指针获取输出的字符:%c\n", *q);

在这里插入图片描述

上面我们说了,指针可以代表数组,而c语言对字符串的定义就是字符数组

char r[] = { "Hello" };
scanf("%s", r);
printf("字符串的值:%s\n", r);

这样我们就可以解释为什么对于获取字符串的时候,不用写&的原因了,因为字符数组本来就是指针!!

二.指针的进阶玩法

2.1 二维指针

由名字可得,二维指针就是指针的指针,指针可以代表数组,自然二维指针就可以代表二维数组

int u[4][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6},{4,5,6,7} };
int** v = u;

二维数组在内存空间上也是线性排列的,就如下顺序
1 2 3 4 2 3 4 5 3 4 5 6 4 5 6 7
所以二维数组获取元素也可以靠索引获取或者移动一维指针

printf("u[1][2]的值:%d\n", v[1][2]);
int* ff = u;
printf("u[1][2]的值为:%d\n",*(ff+5));

也可以动态内存分配实现

int** w = (int**)malloc(4 * sizeof(int)); //分配行内存
for (int i = 0; i < 4; ++i)w[i] = (int*)malloc(4 * sizeof(int)); //分配列内存
for (int i = 0; i < 4; ++i)for (int j = 0; j < 4; ++j)w[i][j] = (j + 1) + i;
printf("w[1][2]的值:%d\n", w[1][2]);
free(w); //记得释放

2.2 结构体指针

先声明一个结构体

struct people
{char* name;int age;
}SPeople;
//方便表示替换掉标识符
typedef struct people People;People dr;
dr.name = "aaa";
dr.age = 18;
printf("dr的名字是:%s,年龄是:%d\n", dr.name, dr.age);People* lp = &dr; //注意属性获取的符号"->"
lp->name = "sss";
lp->age = 19;
printf("lp的名字是:%s,年龄是:%d\n", lp->name, lp->age);

当然也可以动态内存分配使用

People* lps = (People*)malloc(1 * sizeof(People));
lps->name = "xxx";
lps->age = 20;
printf("lps的名字是:%s,年龄是:%d\n", lps->name, lps->age);

结语

指针定义后,在不用时最好指向NULL,比如

int* s = &a;
printf("%p\n", s);
s = NULL;

因为就算释放掉内存,但是指针指向的内存地址依旧可用(获取处于沉睡状态),所以最好不要去动它,不然很容易导致内存泄露
动态声明的指针一定要释放,free函数释放
动态分配内存最好要检查是否成功分配到

int* t = (int*)malloc(10 * sizeof(int));
if (t == NULL)
{//分配错误system("pause");return 0;
}
else
{//你的代码system("pause");free(t);
}

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

相关文章

C语言:指针详解

目录 指针就是地址&#xff0c;口语中说的指针通常指的是指针变量 指针的定义以及指针类型 野指针 指针运算 a.指针/-整数 b.指针只能-指针&#xff0c;不能指针 指针与数组 二级指针 指针数组 指针的大小是固定的4/8个字节&#xff08;32位平台/64位平台&#xff09…

C语言,指针详解

1. 指针是什么&#xff1f; 1. 指针是内存中一个最小单元的编号 2. 口头上的“指针”&#xff0c;指的是指针变量 #include<stdio.h>int main() {int a10;int * pa&a;// pa 是一个指针变量,用来存放 a 的地址//int ——> pa 所指向对象的类型//* 代表 pa是个指针…

C语言指针详细解析

C语言指针详细解析 概述指针指针运算符示例 指针类型示例 指针变量的初始化关系运算示例 数组一维数组示例 二维数组示例 字符串指针示例示例 指针函数示例 函数指针示例 指针函数和函数指针定义写法用途 最后 概述 指针也就是内存地址&#xff0c;指针变量是用来存放内存地址…

C语言:详解指针

本人录制技术视频地址&#xff1a;https://edu.csdn.net/lecturer/1899 欢迎观看。 指针应该算得上是c语言的精华&#xff0c;但也是难点。很多教程或者博客都有对其详细的讲解与分析。我这一节的内容&#xff0c;也是讲解指针&#xff0c;但我会尽量使用图解的方式&#xff0…

【C语言】指针(详解)

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

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

指针 前言一、指针是什么&#xff1f;1.1 认识指针1.2 变量1.3 变量放在哪&#xff1f;1.4 指针的本质1.5 解引用 二、指针类型2.1指针有类型吗&#xff1f;2.2指针类型的意义是什么&#xff1f; 三. 野指针3.1什么是野指针3.2野指针成因3.2.1指针未初始化3.2.2 指针越界访问3.…

【初阶】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;通过一定的算法找出最有用的…