【C语言篇】请把这篇文章推给现在还对指针一知半解的童鞋~超生动图解,详细讲解,易懂,易学,让天下没有难懂的指针~

news2024/11/18 9:42:55

在这里插入图片描述

🌱博主简介:是瑶瑶子啦,一名大一计科生,目前在努力学习C进阶,JavaSE。热爱写博客~正在努力成为一个厉害的开发程序媛!
📜所属专栏:C/C++
✈往期博文回顾:进入内存,透彻理解数据类型存在的意义,整形在内存中存储,大小端字节序,浮点型在内存中存储
🕵️‍♂️近期目标:成为百粉小博主。持续输出:C进阶、JavaSE,数据结构、算法相关的优质博客,
🙇‍♀️写博客理念:力求用通俗语言去阐述知识知识、技术。喜欢画图、思维导图去描述过程和知识之间的联系。
🎡您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!
🌺:“再牛的程序员也是从小白开始,既然开始了,就全身心投入去学习技术”

🙆‍♀️Write int the front
:也许你是将将学C,而为指针百思不得其解的童鞋,也许你是已经玩转指针的大佬~但不管怎么样,我相信,看完这篇文章,一定会对你对指针的理解有很大很大的帮助!让你使用指针的每一步都有满满的安全感!😉话不多说,咱们即刻启程!🚇

🎐区区指针

  • Part1:初识指针--“平平无奇的门牌号罢了”
    • 1.1引入
    • 1.2指针&指针变量
    • 如何理解" * "?
      • 1,指针变量声明时:
      • 2,指针变量前加*:
  • Part2:指针变量也有“类型”
    • 2.1指针变量类型的存在意义:
      • 1,指针的+-运算---------指针的运算是基于类型的
    • 2.2指针+-指针
    • 2.3指针类型对解引用的影响
  • Part3:指针&数组之间的神秘联系
    • 3.1关于数组,你必须知道的:
    • 3.2关于数组,你必须明确的:
    • 3.3指针变量和数组建立联系:
  • Part4:二级指针??
  • Part5:指针数组:
  • Part6:(常量)字符指针
    • 6.1:常量字符串&字符指针之间的关系
  • Part7:数组指针:
    • 7.1数组指针实例及理解:
    • 7.2:数组名 vs &数组名
      • 7.3:数组指针(行指针)怎么用?
  • Part8:学会数组传参的全部方式!
    • 8.1:一维数组传参:
    • 8.2:二维数组传参:
  • Part9:函数也有指针!
    • 9.1函数指针这样声明:

Part1:初识指针–“平平无奇的门牌号罢了”

不知道你学指针的时候有没有这样的疑问,指针变量前面的这个"*"星号是什么,解引用的这个“*”和又是什么,和前者是一样的吗?初次听到“指针”这个“高级名词”是不是也“不寒而栗”(好高级的名字,而且别人都说指针最难学啦–瑶瑶子的亲身感受哈哈)。学校里面老师说“这是行指针,这是列指针,记下来吧,没有别的办法”–(碎碎念:瑶瑶子高程老师说的😅,我内心:???)

(真的没有骗大家,学校里的高程教材!!!老师居然让我把这些全部记下来?????)在这里插入图片描述
🕵️‍♀️这一part,瑶瑶子将带领大家,掀开指针的神秘面纱,通俗移动的解释清楚什么是指针!

1.1引入

  • 👧相信大部分同学都住宿过,住宿的时候,每一间宿舍都有一个门牌号。在这个宿舍楼里,你只要告诉我你的门牌号,我就能找到你的宿舍,并且可以访问你的宿舍(默认我有钥匙),并且可以对你宿舍里的物品进行我想要的处理。
    其实对于计算机的内存来说,你可以把它看作宿舍楼,而指针,其实就是门牌号,通过门牌号,就可以找到对应宿舍,而这个门牌号本质是什么呢?—地址
  • 内存地址是如何产生的?
    answer:我们总是听说,机器有32位,64位?这个32和64指的是什么?其实是地址线,(类似于电线),有两种状态(高低电压),用1,0来表示,在这32/64根地址线运作的过程中,能产生32/64位的0/1序列,每一个序列用来标识内存中最小内存单元(1byte)空间的地址。(32位平台保存一个地址,即0/1序列,需要32bit,4字节,64位需要64bit,8字节)–存储地址所用内存的大小由机器而定。
    在这里插入图片描述

1.2指针&指针变量

🎃虽然上面一直在说指针就是地址,它也确确实实是地址,但是我们更多的时候,说的这个“指针”,指的是指针变量.

  • 什么是指针变量?
    🕋变量,其实就是一个容器,用来存放数据。通过其数据类型来规范变量所占内存空间大小和计算机看待变量的视角以及能对变量进行的操作。⭐(这句话很重要,要好好理解,下面讲的东西其实核心就是这句话!)
    🥙指针变量:固然是存放指针的变量,因为指针其实就是地址,所以,指针变量,就是用来存放地址的变量.

如何理解" * "?

🌟通常," * "会在两种情景下出现:

1.指针变量声明时:
int a=0;
int *p=&a;
 2. 指针被解引用时
int *p=&a;
*p=2;

1,指针变量声明时:

  • * 此时只是一个 标识符,告诉计算机,这是一个存放地址的变量,同时可以被解引用操作符“*”操作(到时候可以通过我来找到我所执行的对象~), 只起说明作用。而把变量名和标识符除去,剩下的这个type,表示的是,p指针变量所指向的那个变量(对象)的类型。

在这里插入图片描述

2,指针变量前加*:

  • 在p变量前单独使用 * 时:此时的 * 是一个 运算符,作用是通过指针变量中的地址,找到所指向对象。间接访问所指向对象,具有 运算功能
    (此时的*p的值就是变量a)

👩‍🏫可以这样理解,比如一个教室里有学生和老师,一个叫小A的同学坐在3排5列的地方,老师想让小A起来回答问题,可以说:小A,你来回答以下问题(喊名字),也可以说:3排5列同学,你来回答一下问题(通过地址,间接找到A)。

Part2:指针变量也有“类型”

🙇‍♀️我们知道,指针变量里面存放的数据是地址,之前文章里我提到过,一个变量的类型同样也表示着所存数据的类型(所以通常讲嘛“XXX变量的数据类型是…")。but ,地址数据有类型吗?答案当然是没有的,地址数据,本身无类型可言,但是指针变量所指向的对象一定有确切的数据类型,由此通常将指针变量所指向对象的数据类型,称为指针变量的数据类型.(说是这么说,但是一般我们还是认为声明变量的时候,去除变量名,剩下的就是变量的数据类型)。

2.1指针变量类型的存在意义:

1,指针的±运算---------指针的运算是基于类型的

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main() {
	int a = 0;
	int *pa = &a;
	printf("%p--> %p\n", pa,pa + 1);
	
	char b = 0;
	char *pb = &b;
	printf("%p--> %p", pb, pb + 1);

	return 0;
}

在这里插入图片描述
🍿:画图理解:
在这里插入图片描述

  • 🌟总结: 指针变量的数据类型,决定了指针变量±整数时,跨过的字节数(内存长度)。

2.2指针±指针

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main() {
	int a = 0;
	int *pa = &a;
	int* pa2 = pa + 1;
	printf("%d", pa2 - pa);//1
	
	return 0;
}

在这里插入图片描述

  • 🌟两个同类型指针相见结果是,两个指针间隔的元素个数。

2.3指针类型对解引用的影响

  • 🌞上面说到了,解引用操作是一种运算,作用是间接访问。但是,计算机是如何知道你要访问和操作多大空间呢?------根据指针的类型来确定。
int a=0;
int *pa=&a;
*a=1;

通过画图,我们来分析:
在这里插入图片描述

  • 🌟指针类型决定了解引用指针的时候,所能间接访问的内存空间,以及看待这份内存空间的视角。

🙆‍♀️在进行Part3之前,请你反问自己几个问题,如果都能回答上来,说明已经对指针有很大掌握了~

  • 普通变量的数据类型的意义是什么?
  • 指针变量类型的意义?

Part3:指针&数组之间的神秘联系

3.1关于数组,你必须知道的:

  • 数组名表示的是?–首元素地址(在main函数中被sizeof()和&操作除外)
  • 二维数组可以看作是一维数组。
  • 🌟arr[i]相当于*(arr+i);
  • 数组名在传参的时候退化成了指针

3.2关于数组,你必须明确的:

  • 数组名指向的是第一个元素的首元素地址(二维数组也看作是一维数组,数组的数组),地址可以用指针变量来接收。
  • 数组存放元素的类型。

3.3指针变量和数组建立联系:

🧙‍♂️有了指针,上面我们提到对于指针变量,有个特有的操作:解引用。所以通过对指针变量解引用,我们可以用指针变量来访问数组元素。

  • 😋举例:

❗注意:由于[ ]的优先级高于*.所以要用括号括起(*p)来表示p是指针。否则p先和[ ]结合,p就代表是个数组了。

int arr[3]={0,1,2};
int *pa=arr;
*(pa+2)=3;
printf("%d",a[2]);
//3

在这里插入图片描述

Part4:二级指针??

🙅‍♀️:碎碎念:这个名字听起来确实还太高级的,但是不要被它吓住了!!!在理清什么是二级指针之前,我们先理清以下概念:

  • 指针变量:(偏正结构),和任何变量一样,本质都是存放数据的容器,在内存中也需要开辟空间。
  • 指针变量的地址:既然指针变量要在内存中开辟空间,上面我们说到过,那么它也有自己的门牌号(地址)!
  • 指针变量的地址谁来存?既然是地址,那肯定有指针变量来存。(逻辑就是这样,一定要理清楚)。
  • 指针变量的定义时,去掉变量名和说明符*之后剩下的这个类型是?上面已经说到过,这是指针变量所指向对象的数据类型。
    在这里插入图片描述

🙆‍♀️弄清楚上面之后,二级指针,其实就是指针变量的地址!

int a=0;
int *pa=&a;
int **ppa=&pa;

在这里插入图片描述

Part5:指针数组:

🙆‍♀️首先,你需要明确以下几点:

  • 指针数组,是数组。
  • 指针数组存放的元素类型是?–指针

类比:char arr[10];arr是字符数组,存放元素类型是字符

int main()
{
	int *arr[5];
	//arr和5结合,说明arr是数组,该数组元素类型是int *
}

在这里插入图片描述

Part6:(常量)字符指针

🤹‍♀️在这之前,你需要知道的:

  • const char * p:常量字符指针,指向的变量类型是const char ,指向对象不能被修改。
  • char * const p:字符常量指针:指针变量p本身不能被修改。

6.1:常量字符串&字符指针之间的关系

🧜‍♂️引入:由于C语言中没有字符串类型,所以,常量字符串用常量字符指针来接收。
所以我们经常能看见:

const char *p="hello";

🧘‍♀️你需要知道的:

  • p存储的是常量字符串首字符的地址。
  • 不能通过指针p对字符串进行修改。
  • C/C++会把常量字符串储存在单独的内存区域中。当两个一模一样的常量字符串存在在程序中时,它们的地址其实是一样的。

Part7:数组指针:

🙆‍♀️首先,你必须明确的:

  • 数组指针,本质是指针。
  • 数组指针变量存放的是数组的地址。
  • 数组指针变量所指向的对象的类型是数组。

7.1数组指针实例及理解:

int main()
{
	char arr[2][3] = { {'a','b','c'},{'d','e','f'} };
	char(*parr)[3] = arr;
}

在这里插入图片描述
👩‍🎓你需要理解的:

  1. 首先arr是一个一维数组的数组。
  2. arr的首元素是arr1,即arr[1]
  3. arr的首元素地址是一维数组arr1的地址
  4. 一维数组的地址需要用一维数组指针变量来接收
  5. ✅parr是一个指针变量,去除说明*和变量名之后,该类型是所指向对象的类型–一维数组。

7.2:数组名 vs &数组名

int arr[3]={1,2,3};
int (*parr)[3]=&arr;
int *p=arr;

相同点

  • 均为指针

不同点

  • arr指向对象的类型是int,&arr指向对象类型是int [3]
  • arr+1跨过的字节数是4,(&arr)+1跨过的字节数是4*3

7.3:数组指针(行指针)怎么用?

💁‍♀️这里讲其中一个用法:使用行指针打印二维数组。

int main()
{
	int arr[2][3] = {1,2,3,4,5,6};
	int (*p)[3] = arr;
	for (int i = 0;i < 2;i++)
	{
		for (int j = 0;j < 3;j++)
		{
			printf("%d",*(p+i)[j];
		}
	}
	return 0;
}

🤷‍♀️如何理解*(p+i)[j](对照上方的图,把char转成int就行)

  • *(p+i)找到了arr1(或arr2),即*(p+i)=arr1,p=&arr1(首元素地址)
  • 所以*(p+i)[j]相当于arr1[j]
    在这里插入图片描述

Part8:学会数组传参的全部方式!

💁‍♀️你必须明确的,什么类型变量可以接收数组传参

  • ✅数组传参,数组接收–形参为数组
  • ✅数组传参,指针接收(因为数组名表示啥?你自己说🤩)

8.1:一维数组传参:

int main()
{
	char arr[3]={'a','b','c'};
	test(arr);
	return 0;
}

😍3种接收方式:

  • void test (char arr[]);
  • void test (char arr[3]);
  • void test (char *arr);

8.2:二维数组传参:

int main()
{
	char arr[2][3]={'a','b','c','e','f','g'};
	test(arr);
	return 0;
}

😍3种接收方式:

  • void test(char (*arr) [3]);
  • void test(char arr[2][3]);
  • void test(char arr[][3];

🧙‍♂️:注意,二维数组传参,用二维数组来接收时 ,行参数可以省略,列参数不能省略。其实还是用之前的想法,把二维数组看作一维数组。那么数组的一个元素类型就是一维数组,不知道该一维数组长度(就是二维数组列长)就相当于不知道一个一维数组的数组元素的类型一样。

🌊易错!!

  • 为什么不能用char ** arr来接收?
    -答:始终要清楚,用指针来接收,你必须明确所指向的类型是不是一样的,因为指针所指向对象的类型确定了?(你自己说🤗)。而char *和char [3]是完全不同的两种数据类型!(起码所占内存的大小就不同~)。

Part9:函数也有指针!

🐳你需要知道的:

  • 函数名表示函数指针(函数地址)。

9.1函数指针这样声明:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int add(int x, int y) {
	return x + y;
}
int main() {
	int (*p)(int, int) = add;
//返回类型   //形参1,2类型  
	return 0;
}

👼建议:表示指针时,最好都用(*p)这种括号来明确,否则指针变量一不小心就和其他符号结合了哟~

  • 利用函数指针来调用函数
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int add(int x, int y) {
	return x + y;
}
int main() {
	int (*p)(int, int) = add;
//返回类型   //形参1,2类型  
	int ret=p(1,2);
	return 0;
}

😎write in the end
以上就是指针基础知识的全部内容了!!!
理解好了指针,用起来安全感也会up up up!
🙋‍♀️再也不会畏惧指针啦,相信你下次看到指针,内心:区区指针,你占多少字节,指向什么类型的变量,我都看的看的透透的!!
🙆‍♀️原创不易,画图不易,如果有帮助,还请多多点赞,关注,收藏,评论~咱们下期见💦

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/163844.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[java拓展]Mysql数据库的基础指令,和JDBC的使用

1.关于mysql数据库 &#xff08;1&#xff09;概述 DBMS数据库管理系统&#xff0c;用来管理数据库&#xff0c;执行sql语句的东西&#xff0c;Mysql&#xff0c;oracle&#xff0c;sqlite这些严格来说不是数据库而是数据库管理系统&#xff0c;其中Mysql最常用&#xff0c;而…

马来酰亚胺聚乙二醇硅烷,MAL-PEG-Silane 结构,科研试剂溶于大部分有机溶剂

马来酰亚胺聚乙二醇硅烷&#xff0c;MAL-PEG-Silane 中文名称&#xff1a;马来酰亚胺聚乙二醇硅烷 分子量&#xff1a;1k&#xff0c;2k&#xff0c;3.4k&#xff0c;5k&#xff0c;10k&#xff0c;20k。。。 存储条件&#xff1a;-20C&#xff0c;避光&#xff0c;避湿 用…

剑指offer----C语言版----第十九天----面试题25:合并两个有序的链表

目录 1. 合并两个排序的链表 1.1 题目描述 1.2 解题思路 1.3 往期回顾 1. 合并两个排序的链表 原题链接&#xff1a;21. 合并两个有序链表 - 力扣&#xff08;LeetCode&#xff09;1.1 题目描述 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个…

new-Crack:StarUML 5.1.0 -2023

StarUML 用于敏捷和简洁建模的复杂软件建模器 当前版本&#xff1a;v5.1.0 主要特征 通用语言2 兼容 UML 2.x 标准元模型和图表&#xff1a;类、对象、用例、组件、部署、复合结构、序列、通信、状态图、活动、时间、交互溢出、信息流和剖面图。 SYSML 支持 支持使用 SysML 图…

SSM03_SpringMVC REST风格 SSM整合

01-SpringMVC简介SpringMVC是隶属于Spring框架的一部分&#xff0c;主要是用来进行Web开发&#xff0c;是对Servlet进行了封装。SpringMVC是处于Web层的框架&#xff0c;所以其主要的作用就是用来接收前端发过来的请求和数据然后经过处理并将处理的结果响应给前端&#xff0c;所…

【iHooya】1月14日寒假集训课作业解析

内部元素之和 输入一个整数矩阵&#xff0c;计算位于矩阵内部的元素之和。所谓矩阵内部的元素&#xff0c;不在第一行和最后一行的元素以及第一列和最后一列的元素。 输入 第一行分别为矩阵的行数m和列数n&#xff08;m < 100&#xff0c;n < 100&#xff09;&#xff0…

Arthas 入门到实战(一)快速入门

Arthas官方文档指出&#xff1a; 介绍&#xff1a;Arthas 是一款线上监控诊断产品&#xff0c;通过全局视角实时查看应用 load、内存、gc、线程的状态信息&#xff0c;并能在不修改应用代码的情况下&#xff0c;对业务问题进行诊断&#xff0c;包括查看方法调用的出入参、异常&…

人工智能与游戏

游戏是智能应用最好的平台&#xff0c;可惜的是&#xff1a;只用了少部分计算AI&#xff0c;还没有用到智能的计算计1 引言从1950年香农教授提出为计算机象棋博弈编写程序开始&#xff0c;游戏人工智能就是人工智能技术研究的前沿&#xff0c;被誉为人工智能界的“果蝇”&#…

微信小程序070校园食堂订餐多商家带配送

基于微信小程序食堂订餐管理系 系统分为用户和管理员&#xff0c;商家三个角色 用户小程序端的主要功能有&#xff1a; 1.用户注册和登陆小程序 2.查看系统新闻资讯公告 3.用户查看小程序端的菜品信息&#xff0c;在线搜索菜品&#xff0c; 4.用户查看菜品详情&#xff0c;收…

数据结构-二叉搜索树解析和实现

1.含义规则特性二叉搜索树也叫排序二叉树、有序二叉树&#xff0c;为什么这么叫呢&#xff1f;名字由来是什么&#xff1f;主要是它的规则图一规则一&#xff0c;左子树的所有节点的值均小于它的根节点的值规则二&#xff0c;右子树的所有节点的值均大于它的根节点的值&#xf…

摇头测距小车01_舵机和超声波代码封装

目录 一、摇头测距小车图片演示 二、接线方式 三、代码实现 一、摇头测距小车图片演示 就是在小车原有的基础上&#xff0c;在小车前面加一个舵机和一个超声波&#xff0c;把超声波粘在舵机上 二、接线方式 1、超声波接线 VCC-----上官一号5V GND----上官一号GND Trig----…

.net开发安卓入门-Dialog

.net开发安卓入门-DialogAndroid.App.AlertDialog运行效果代码UI源码引入 下面这个类库才可以使用Java.Interop.Export特性绑定事件Android.App.AlertDialog https://learn.microsoft.com/zh-cn/dotnet/api/android.app.alertdialog?viewxamarin-android-sdk-13 SetTitle &…

nodejs+vue摄影跟拍预定管理系统

&#xff0c;本系统分为用户&#xff0c;摄影师&#xff0c;管理员三个角色&#xff0c;用户可以注册登陆系统&#xff0c;查看摄影套餐&#xff0c;预约套餐&#xff0c;购买摄影周边商品&#xff0c;查看跟拍照片等。摄影师可以对用户的摄影预约审核&#xff0c;跟拍流程管理…

【Java集合】ArrayList自动扩容机制分析

目录 先从 ArrayList 的构造函数说起 一步一步分析 ArrayList 扩容机制 先来看 add 方法 再来看看 ensureCapacityInternal() 方法 ensureExplicitCapacity()和calculateCapacity方法 下面我们接着来看grow() 方法 再来看一下grow()中调用的hugeCapacity() 方法 System.arrayco…

3、代码注释与编码规范

目录 一、代码注释 &#xff08;1&#xff09;单行注释 &#xff08;2&#xff09;多行注释 &#xff08;3&#xff09;文档注释 2. 编码规范 一、代码注释 &#xff08;1&#xff09;单行注释 “//”为单行注释标记&#xff0c;从符号“//”开始直到换行为止的所有内容…

3D立体字生成器【免费在线工具】

Text2STL是一个可以在线使用的免费的3D立体字生成工具&#xff0c;输入文字内容即可实时预览生成的3D立体字模型&#xff0c;还可以导出为STL模型用于3D打印&#xff1a; 3D立体字生成器访问地址&#xff1a; http://text2stl.bimant.com/zh-cn/generator 1、3D立体字生成风…

【零基础】学python数据结构与算法笔记11

文章目录前言65.树的概念66.树的实例&#xff1a;模拟文件系统67.二叉树的概念68.二叉树的遍历69.二叉搜索树的概念。70.二叉搜索树&#xff1a;插入71.二叉搜索树&#xff1a;查询72.二叉搜索树&#xff1a;删除73.二叉搜索树&#xff1a;删除实现总结前言 学习python数据结构…

中本聪是个贪婪的矿工吗?

对可能是中本聪的实体所表现出的挖矿行为的技术分析。文 | Jameson Lopp. 原标题&#xff1a;Was Satoshi a Greedy Miner?. 2022/9/16.* * *如果你在加密生态系统中待了足够久的时间&#xff0c;那么你无疑会听到这样的论点&#xff0c;即某些项目的代币分配不公平&#xff0…

Windous注册表+c#操作

下面将会分享注册表的基础知识及C# 读写注册表的方法 了解注册表 注册表&#xff08;英语&#xff1a;Registry&#xff0c;中国大陆译作注册表&#xff0c;台湾、港、澳译作登录档&#xff09;是Microsoft Windows操作系统和其应用程序中的一个重要的层次型数据库&#xff0…

关于计算机网络,你需要知道的一些常识

最近闲着没啥事翻开之前大学时候谢希仁老师第7版的《计算机网络》这本书,结果发现了一些之前没有发现的常识。 首先是互联网与互连网的区别,一般我们常说的互联网是Internet,是指因特网,其起源于阿帕网ARPANT。或许很多读者看到这里就觉得有什么秘密可言,不都是常识了吗?看你大…