【C语言初阶】C语言指针全攻略:解锁C语言深层奥秘的钥匙

news2025/1/9 5:49:59

📝个人主页🌹:Eternity._
⏩收录专栏⏪:C语言 “ 登神长阶 ”
🤡往期回顾🤡:C语言操作符
🌹🌹期待您的关注 🌹🌹

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

❀指针

  • 📒1. 指针和指针类型
    • 🌄指针的概念
    • 🏞️指针 + - 整数
    • ⛰️指针的解引用
  • 📙2. 野指针
    • 🎈野指针成因
    • 🎩如何规避野指针
  • 📕3. 指针运算
    • 🍁指针 - 指针
    • 🍂指针的关系运算
  • 📚4. 指针和数组
  • 📜5. 二级指针
  • 📝6. 指针数组
  • 📖7. 总结


前言:在编程的广阔天地里,C语言以其接近硬件的特性和强大的灵活性,始终占据着举足轻重的地位。而在这片由代码构建的领域中,指针无疑是那把开启C语言深层奥秘的钥匙。它不仅让程序员能够直接访问和操作内存,更是构建复杂数据结构、实现高效算法、进行底层开发不可或缺的工具

对于许多初学者而言,指针或许是一个令人望而生畏的概念。那些看似晦涩难懂的语法规则和抽象的概念,常常让人望而却步。然而,正如攀登高峰的过程虽然艰难,但一旦站在山顶,便能领略到前所未有的壮丽景色。学习C语言指针,也是一场从迷茫到清晰、从畏惧到掌握的旅程

在这篇文章中,我们将一起踏上这段旅程,从指针的基础概念讲起,逐步深入到内存管理、数组操作、函数参数传递等核心话题。我们将通过生动的示例、清晰的解释和实用的技巧,帮助你克服对指针的恐惧,逐步建立起对指针的深刻理解和灵活运用能力

让我们一起,用指针这把钥匙,打开C语言世界的大门,探索其中的无限可能和精彩世界!


📒1. 指针和指针类型

🌄指针的概念

指针理解的2个要点:

  • 指针是内存中一个最小单元的编号,也就是地址
  • 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量

总结:指针就是地址


在这里插入图片描述
指针变量

我们可以通过&(取地址操作符)取出变量的内存其实地址,把地址可以存放到一个变量中,这个变量就是指针变量

代码示例 (C语言):

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

指针变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)


对于32位的机器,假设有32根地址线

那么32根地址线产生的地址就会是:

//00000000 00000000 00000000 00000000
//00000000 00000000 00000000 00000001
...
//11111111 11111111 11111111 11111111

这里就有2的32次方个地址。
每个地址标识一个字节,那我们就可以给
(2^32Byte == 2^32/1024KB == 2^32/1024/1024MB == 2^32/1024/1024/1024GB == 4GB)
4G的空间进行编址

  • 在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节
  • 那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址

总结:

  • 指针变量是用来存放地址的,地址是唯一标示一个内存单元的
  • 指针的大小在32位平台是4个字节,在64位平台是8个字节

🏞️指针 + - 整数

代码示例 (C语言):

int main()
{
	int n = 10;
	char* pc = (char*)&n;
	int* pi = &n;
	printf("%p\n", &n);
	printf("%p\n", pc);
	printf("%p\n", pc + 1);
	printf("%p\n", pi);
	printf("%p\n", pi + 1);
	return 0;
}

指针的类型决定了指针向前或者向后走一步有多大(距离)


⛰️指针的解引用

代码示例 (C语言):

int main()
{
	int n = 0x11223344;
	char* pc = (char*)&n;
	int* pi = &n;
	*pc = 0; //重点在调试的过程中观察内存的变化。
	*pi = 0; //重点在调试的过程中观察内存的变化。
	return 0;
}

在这里插入图片描述

指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)
比如: char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节


📙2. 野指针

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


🎈野指针成因

指针未初始化

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

指针越界访问

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

指针指向的空间释放

(动态内存开辟的时候会提及… …)


🎩如何规避野指针

  • 指针初始化
  • 小心指针越界
  • 指针指向空间释放,及时置NULL
  • 避免返回局部变量的地址
  • 指针使用之前检查有效性
int main()
{
	int* p = NULL;
	//....
	int a = 10;
	p = &a;
	if (p != NULL)
	{
		*p = 20;
	}
	return 0;
}

📕3. 指针运算

🍁指针 - 指针

指针 - 指针表示两个指针相隔的距离

int main()
{
	int a = 10;
	int* p1 = &a;
	int* p2 = p1;
	p1++;
	printf("%d", p1 - p2);
	return 0;
}

🍂指针的关系运算

指针之间不能直接使用 <、>、<=、>= 进行比较,除非这些指针:

  • 指向同一个数组的元素
  • 指向同一个结构体(或联合体)的不同成员

对于指向不同数组或不同对象的指针,进行关系运算的结果是未定义的

标准规定:

  • 允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较

📚4. 指针和数组

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存放的是数组首元素的地址

我们可以通过数组名来访问数组元素

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,0 };
	int* p = arr; //指针存放数组首元素的地址
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < sz; i++)
	{
		printf("&arr[%d] = %p <====> p+%d = %p\n", i, &arr[i], i, p + i);
	}
	return 0;
}

在这里插入图片描述
p+i 其实计算的是数组 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; i < sz; i++)
	{
		printf("%d ", *(p + i));
	}
	return 0;
}

📜5. 二级指针

二级指针储存指针变量的变量

在这里插入图片描述

关于二级指针:

  • *ppa 通过对ppa中的地址进行解引用,这样找到的是 pa , ppa 其实访问的就是 pa
int b = 20;
*ppa = &b;//等价于 pa = &b;

  • **ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a
**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;

📝6. 指针数组

指针数组储存指针的数组

int arr1[5];
char arr2[6];

在这里插入图片描述

int* arr3[5];

arr3是一个数组,有五个元素,每个元素是一个整形指针
在这里插入图片描述


📖7. 总结

在探索C语言指针的旅途中,我们不难发现,指针不仅是C语言强大功能的核心,也是理解底层内存管理和高级编程技巧的关键。通过深入学习和实践,我们逐渐揭开了指针神秘的面纱,掌握了它们如何像桥梁一样连接起变量、数组、结构体乃至更复杂的数据结构

在本文的结尾,我想强调的是,掌握C语言指针并非一蹴而就的过程,它需要时间的积累、实践的锤炼以及对错误和困惑的不懈探索。每一次对指针的深入理解,都是对C语言编程能力的一次飞跃,也是对自己逻辑思维和问题解决能力的一次提升

同时,我们也要认识到,指针虽然强大,但使用时必须格外小心。错误的指针操作可能导致内存泄露、野指针、段错误等一系列问题,严重影响程序的稳定性和安全性。因此,在享受指针带来的便利和效率的同时,我们也必须时刻铭记其潜在的风险,并养成良好的编程习惯,如初始化指针、检查空指针、合理使用指针类型等

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

于博士Cadence视频教程学习笔记备忘

标签&#xff1a;PCB教程 PCB设计步骤 cadence教程 Allegro教程 以下是我学习该视频教程的笔记&#xff0c;记录下备忘&#xff0c;欢迎大家在此基础上完善&#xff0c;能回传我一份是最好了&#xff0c;先谢过。 备注&#xff1a; 1、未掌握即未进行操作 2、操作软件是15.…

【问题记录+总结】VS Code Tex Live 2024 Latex Workshop Springer模板----更新ing

目录 Summary 道阻且长 少即是多 兵马未动粮草先行 没有万能 和一劳永逸 具体问题具体分析 心态 Detail 1、关于模板[官网] 2、settings.json 3、虫和杀虫剂 4、擦 换成Tex Studio都好了。。。 Summary 道阻且长 某中意期刊&#xff0c;只有Latex。之前只简单用过…

VSCODE platformio ESP32-S3 内置 JTAG 接口断点单步调试笔记

ESP32 S3的两种JTAG调试方法 ESP32 S3的有两种JTAG调试方法&#xff0c;直接连接板子上的JTAG引脚进行调试&#xff0c;或者用ESP32-S3 内置 JTAG 接口进行调试&#xff0c;这些方法有助于开发者在开发过程中进行更深入的调试。 1、ESP32-S3 内置 JTAG 接口 使用 ESP32-S3 内…

第63期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以找…

如何使用unittest和pytest进行python脚本的单元测试

1. 关于unittest和pytest unittest是python内置的支持单元测试的模块&#xff0c;他提供了核心类&#xff0c;TestCase&#xff0c;让单元测试 代码的编写不再是从0开始&#xff0c;不再是作坊式&#xff0c;而是标准化&#xff0c;模板化&#xff0c;工厂化。 pytest是第三方…

微软官方U盘制作工具重装Windows11系统教程

微软官方U盘制作工具重装Windows11系统教程 **注意&#xff1a;**在安装系统的过程中&#xff0c;有可能会因为操作失误造成硬盘原有数据丢失&#xff0c;建议大家要提前做好重要资料备份&#xff0c;避免出现无法挽回的损失。 ​ Windows 11 对于大部分用户而言是完全没有使用…

国产JS库(js-tool-big-box)7月度总结

js-tool-big-box开发已经有3个月了&#xff0c;团队内的小伙伴进行了热烈的讨论&#xff0c;持续做了功能迭代。小伙伴们也做了艰苦卓绝的文档分享&#xff0c;有纯功能分享类的&#xff0c;有带有小故事的&#xff0c;有朋友们利用自己独自网站分发分享的。7月份快要结束了&am…

【云原生】Pass容器研发基础——汇总篇

云原生基础汇总 系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了云计算学习的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;每个知识点的修正和深入主要参考各平台大佬的文章&#xff0c…

Backtrader 文档学习- 整体架构功能分析理解

Backtrader 文档学习- 架构功能分析理解 1. 概述 backtrader是一个用于开发和执行交易策略的Python框架。它提供了一套完整的工具和功能&#xff0c;使得用户可以方便地进行策略回测、实盘交易以及数据分析。 backtrader的入口为Cerebro类&#xff0c;该类将所有输入(Data F…

FPGA学习笔记-1 FPGA原理与开发流程

1 初识FPGA 文章目录 1 初识FPGA1.1 基本认知1.1.1 什么是FPGA&#xff1f;1.1.2 什么是HDL&#xff1f;什么是Verilog&#xff1f;1.1.3 硬件开发与软件开发1.1.4 FPGA与其他硬件的对比1.1.5 FPGA优势与局限性1.1.6 FPGA的应用1.1.7 FPGA的学习之路 1.2 FPGA开发流程1.2.1 一般…

【学习AI-相关路程-概念了解-基础概念-正负样本-模型-文件结尾-卷积-yolov8模型-概念学习】

【学习AI-相关路程-概念了解-基础概念-正负样本-模型-文件结尾-卷积-yolov8模型-概念学习】 1、前言2、了解正负样本1-定义2-正样本3-负样本4-举例 3、模型这个概念1- 模型的定义2- 模型的训练3- 模型的推理4- 模型的评估5- 模型的类型6- 常见的模型 4、以这样 .yaml 结尾文件是…

以太坊私有链 搭建及相关操作

文章目录 1、创建私有链1.1 创建配置文件1.2 初始化私有链1.3 启动私有链1.4 添加节点1.4.1 启动节点A1.4.2 启动节点B1.4.3 查看节点A信息1.4.4 节点B主动加入到节点A1.4.5 查看已连接的节点数1.4.6 查看其它节点信息2、以太坊挖矿相关操作2.1 查看账户2.2 创建账户2.3 查看账…

RUST实现远程操作电脑手机

简介&#xff1a; Rust Desk 是一个开源的远程桌面软件&#xff0c;能够完全替代向日葵和ToDesk的功能&#xff0c;包括电脑控制电脑、电脑控制手机、手机控制电脑等。它是完全免费的。 下载&#xff1a; 需要下载 Rust Desk 的服务端和客户端安装包。 安装&#xff1a; 服务…

PHP移动端商城分销全平台全端同步使用

&#x1f4f1;【掌中购物新纪元&#xff1a;探索移动端购物商城系统的无限魅力】&#x1f6cd;️ &#x1f680; 随时随地&#xff0c;购物自由新体验 在这个快节奏的时代&#xff0c;移动端购物商城系统彻底颠覆了传统购物方式&#xff0c;让消费者享受到了前所未有的便捷与…

探索RPA自动化流程机器人在财务领域的应用

随着科技的不断发展&#xff0c;企业对于流程自动化的需求日益增长。在此背景下&#xff0c;RPA机器人流程自动化技术应运而生&#xff0c;并在财务领域展现出强大的应用潜力。RPA能够模拟人类在计算机上的操作&#xff0c;自动化处理大量重复、繁琐的财务流程&#xff0c;为企…

linux共有云主机ssh升级(以openEuler22.03为例)

目录 为什么要升级ssh怎么查看CVE如何查找新版本的opensshOpenSSH 升级ssh步骤1. 下载源码包2. 备份旧文件防止升级失败3. 停止并卸载旧ssh4. 解压、编译、编译安装新ssh5. 修改systemd文件以便systemctl使用sshd6. 测试 为什么要升级ssh openssh作为使用最为广泛的linux下ssh…

机器学习——线性回归(sklearn)

目录 一、认识线性回归 1. 介绍 2. 多元线性回归的基本原理&#xff08;LinearRegression&#xff09; 二、多重共线性 1. 介绍 2. 多重共线性详细解释 三、岭回归&#xff08;解决多重共线性问题&#xff09; 1. 模型推导 2. 选取最佳的正则化参数取值 四、Lasso&am…

(寄中寄) docker destop 的wsl问题——记一次在win10虚拟机的上的启动docker

&#x1f3aa;&#x1f3a2;&#x1f3a1;&#x1f3a0;&#x1f921;&#x1f981; 在win10上可能可以用docker&#xff0c;不过在win10上用docker有点不可能 wsl在windows中可能需要安装&#xff0c;不过wsl在windows安装有点不可能 应该是不用安装吧 可能需要重启 然后 …

移动运维APP项目建设:重塑运维服务新范式

在当今信息化高速发展的时代&#xff0c;信息系统已成为企业运营的核心支撑。为确保信息系统稳定、高效运行&#xff0c;运维团队面临着前所未有的挑战。传统运维方式受限于固定场所和设备&#xff0c;难以满足随时随地访问、快速响应等现代运维需求。因此&#xff0c;依托现有…

uniapp自定义navigationBar

最终效果&#xff1a; 一、关闭默认导航栏 pages.json文件中&#xff0c;对单个页面关闭 "navigationStyle": "custom" "pages": [ //pages数组中第一项表示应用启动页&#xff0c;参考&#xff1a;https://uniapp.dcloud.io/collocation/pag…