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

📝个人主页🌹: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.rhkb.cn/news/402446.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端各种文本文件预览 文本编辑excel预览编辑 pdf预览word预览 excel下载pdf下载word下载

前端各种文本文件预览 文本编辑excel预览编辑 pdf预览word预览 excel下载pdf下载word下载 各种文本文件预览&#xff08;pdf, xlsx, docx, cpp, java, sql, py, vue, html, js, json, css, xml, rust, md, txt, log, fa, fasta, tsv, csv 等各种文本文件&#xff09; 其中 除p…

C 408—《数据结构》算法题基础篇—数组(通俗易懂)

目录 Δ前言 一、数组的合并 0.题目&#xff1a; 1.算法设计思想&#xff1a; 2.C语言描述&#xff1a; 3.算法的时间和空间复杂度 : 二、数组元素的倒置 0.题目 : 1.算法设计思想 : 2.C语言描述 : 3.算法的时间和空间复杂度 : 三、数组中特定值元素的删除 0.题目 : …

SpringBoot3 + Flowable7 工作流引擎使用笔记

目录 Flowable 简介流程设计器安装使用 SpringBoot 3 整合表结构流程部署启动流程流程审批流程挂起和激活任务分配固定分配表达式分配值表达式方法表达式 监听器分配 流程变量运行时变量历史变量 身份服务候选人拾取任务归还任务指派给别人候选人组创建用户创建用户组用户关联用…

VueUse 基于 Vue 3 Composition API 的高质量 Hooks 库

VueUse 是什么? VueUse 是基于 Vue 3 Composition API 的高质量 Hooks 库。例如获取滚动的距离 VueUse 官网:VueUse | VueUse VueUse 什么使用? 1、通过npm安装 VueUse npm i @vueuse/core 2、搜索需要使用的函数,例如搜索 useScroll 滚动 3、使用useScroll 滚动函数 …

C语言传递指针给函数

C 语言允许您传递指针给函数&#xff0c;只需要简单地声明函数参数为指针类型即可。 下面的实例中&#xff0c;我们传递一个无符号的 long 型指针给函数&#xff0c;并在函数内改变这个值 实例1&#xff1a;获取系统的时间值 能接受指针作为参数的函数&#xff0c;也能接受数…

为什么Pandas是最流行的Python数据分析库?

本文将从Python生态、Pandas历史背景、Pandas核心语法、Pandas学习资源四个方面去聊一聊Pandas&#xff0c;期望能带给大家一点启发。 一、Python生态里的Pandas 五月份TIOBE编程语言排行榜&#xff0c;Python追上Java又回到第二的位置。Python如此受欢迎一方面得益于它崇尚简…

零成本 API 服务搭建,用 GitHub Actions 自动爬取文章?

前言 本着将成本降到最低&#xff0c;我目前做的应用或小程序都是单机的&#xff0c;也就是不用请求接口&#xff0c;只要一上架就没有任何支出。但是写死的数据毕竟有限&#xff0c;应用的内容单一无法紧跟时事热点&#xff0c;每次打开一个样&#xff0c;自然就没有留存。遇…

Redis13-多级缓存

目录 概述 JVM进程缓存 Caffeine 实现进程缓存 Lua语法 初识Lua 变量和循环 Lua的数据类型 声明变量 循环 条件控制、函数 函数 条件控制 实现多级缓存 安装OpenResty OpenResty快速入门 请求参数处理 查询Tomcat 发送http请求的API 封装http工具 CJSON工…

CSS小玩意儿:文字适配背景

一&#xff0c;效果 二&#xff0c;代码 1&#xff0c;搭个框架 添加一张背景图片&#xff0c;在图片中显示一行文字。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" conte…

【Python】高效的Web自动化测试利器—Python+Playwright快速上手自动化实战指南(限时开放)

文章目录 前言一.playwright是什么二.python引入playwright1.安装2.playwright命令行参数3.playwright codegen自动生成代码4.Chrome和Chromium有什么关系&#xff1f; 三.基本概念1. 无头浏览器&#xff08;Headless Browser&#xff09;2.同步和异步模式操作playwright2.1.同…

SQL每日一练-0815

今日SQL题难度&#xff1a;&#x1f31f;☆☆☆☆☆☆☆☆☆ 1、题目要求 计算每个产品类别在每个月的总销售额和总销量。找出每个月销售额最高的产品类别&#xff0c;显示类别名称、销售月份、总销售额和总销量。 2、表和虚拟数据 现有两个表&#xff1a;Products 和…

RockerMQ学习

消息中间件以前常用RabbitMQ和ActiveMQ&#xff0c;由于业务需要&#xff0c;后期业务偏向大数据&#xff0c;现着重学习一下RocketMQ&#xff08;RocketqMQ原理同ctg-mq&#xff09;&#xff0c;后续更新Kafka 一、RocketMQ特性 Kafka特性 &#xff08;高性能分布式&#xff…

day34-nginx常用模块

## 0. 网络面试题 网络面试题: TCP三次握手 TCP四次挥手 DNS解析流程 OSI七层模型 抓包工具 tcpdump RAID级别区别 开机启动流程 如何实现不同的网段之间通信(路由器) ip route add 192.168.1.0 255.255.255.0 下一跳的地址或者接口 探测服务器开启了哪些端口(无法登录服务器…

渗透测试-行业术语

1.肉鸡 肉鸡用来比喻哪些可以随意被我们控制的计算机&#xff0c;可以是普通的个人电脑&#xff0c;也可以是大型服务器或者其他网络设备&#xff0c;我们可以像操作自己的电脑一样操作他们而不被发觉。 2.木马 表面上伪装成了正常程序&#xff0c;但是当程序被运行的时候&a…

配置MySQL主从,配置MySQL主主 +keeplive高可用

在大数据-Hadoop体系中 配置MySQL主主keeplive高可用 注意&#xff1a;这个是我两年前的word文档&#xff0c;可以当作参考文档有个思路参考一下&#xff0c;但是里面可能有些地方有误 另外 :关于一些企业级实战技术可以参考这篇mysql 物理备份 MySQL 全量备份 增量备份 差异…

Linux_vi vim的使用

目录 vi和vim的基本介绍 vi和vim常用的三种模式 案例演示 vim的快捷键 快捷键使用练习 vi和vim的基本介绍 linux系统内会内置vi文本编译器。vim可以简单认为是vi的增强版本。 vi和vim常用的三种模式 有正常模式&#xff0c;移动光标&#xff0c;删除字符等。插入模式可以进…

Flask 线上高并发部署方案实现

目录 1、Flask默认多线程执行 2、使用gevent.pywsgi实现 3、是用uWSGI服务器实现 1、Flask默认多线程执行 前言&#xff1a;在Flask的较早版本中&#xff0c;默认并不支持多线程模式。然而&#xff0c;从Flask 0.9版本开始&#xff0c;引入了多线程模式的支持&#xff0c;并…

【自动驾驶】ROS中的TF坐标变换(一):静态坐标变换

目录 引子ros中的右手坐标系补充&#xff1a;欧拉角及四元数理解旋转平移操作复合操作 运行坐标变换的例子坐标转换 静态坐标变换-发布坐标系信息创建功能包 静态坐标变换-订阅坐标系信息添加cpp订阅者主文件修改cmakelist文件编译报错的解决方案运行程序进行测试 引子 机器人…

【MySQL数据库】单机、集群、分布式的区别

单机、集群和分布式是计算机系统中三种不同的架构模型,它们在资源管理、任务执行和性能优化方面有显著区别。 图片来源 1. 单机(Standalone) 单机指的是单一计算机系统,即所有的计算任务和数据都在一台计算机上处理。单机系统的特点包括: 硬件限制:受限于单台机器的计…

Visual Studio 2022 无法打开源文件atlimage.h

最近在搞tcp socket 通信demo&#xff0c;网上抄了一下源码&#xff08;代码参考&#xff1a;C中的Socket编程使用协议发送图片_快速传输 照片 c-CSDN博客&#xff09;&#xff0c;还没开始编译就提示 无法打开源文件atlimage.h&#xff0c;全局搜了一下没有这个文件&#xff0…