(C语言)深入理解指针1基础

指针是C语言中的一个难点,但如果真正理解了指针,其实没有很难,本篇文章介绍了指针的基础知识,后面还会继续更行指针的内容。感谢支持。

目录

1. 内存和地址

1.1 内存

1.2 究竟该如何理解编址

2. 指针变量和地址

2.1 取地址操作符(&)

2.2 指针变量和解引⽤操作符(*)

2.2.1 指针变量

2.2.2 如何拆解指针类型

2.2.3 解引⽤操作符

2.3 指针变量的⼤⼩

3. 指针变量类型的意义

3.1 指针的解引⽤

3.2 指针+-整数

3.3 void* 指针

4. const修饰指针

4.1 const修饰变量

4.2 const修饰指针变量

5. 指针运算

5.1 指针+- 整数

5.2 指针-指针

5.3 指针的关系运算


1. 内存和地址

1.1 内存

CPU( 中央处理器) 在处理数据的时候 ,需要的数据是在内存中读取的 ,处理后的数   据也会放回内存中 ,那我们买电脑的时候  电脑上内存是8GB/16GB/32GB等 内存划分为一个个的内存单元 ,每个内存单元的大小取1个字节,方便高效管理。

计算机中常见的单位

其实每个内存单元都有自己的唯一确定的编号,通过这个编号,CPU就可以快速,找到对应的内存空间,这个编号也就是地址,在C语言中也有一个名字叫作:地址。

我们可以理解为:内存单元的编号==地址==指针

1.2 究竟该如何理解编址

CPU访问内存中的某个字节空间 ,必须知道这个 字节空间在内存的什么位置 ,而因为内存中字节很多 ,所以需要给内存进行编址(就如同宿舍很 ,需要给宿舍编号一样)。

计算机中的编址 ,并不是把每个字节的地址记录 下来 ,而是通过硬件设计完成的。

首先 ,必须理解 ,计算机内是有很多硬件单元,而硬件单元是要互相协同工作的。所谓的协 ,至少相互之间要能够进行数据传递。

但是硬件与硬件之间是互相独立的 ,那么如何通信呢?答案很简单 ,用"线"连起来。

而CPU和内存之间也是有大量的数据交互的 ,所 ,两者必须也用线连起来。

不过 ,我们今天关心一组线 ,叫做地址总线

我们可以简单理解,32位机器有32根地址总线,每根线只有两态 ,表示0或1【电脉冲有无】 ,那么一根线 ,就能表示2种含义 ,2根线就能表示4种含  ,依次类推。32根地址线 ,就能表示2^32种含   ,每一种含义都代表一个地址。

地址信息被下达给内存 ,在内存上 ,就可以找到该地址对应的数据 ,将数据在通过数据总线传入 CPU内寄存器。

2. 指针变量和地址

2.1 取地址操作符(&)

理解了内存和地址的关系,我们再回到C语⾔,在C语⾔中创建变量其实就是向内存申请空间,

我们知道C语言中一个整形占4个字节,创建时会向内存申请4字节的空间,当取整形变量的地址时会取出4个字节地址的第一个地址,因为知道是int类型,当需要这个变量时就能顺藤摸瓜,将这4个字节全部访问。

2.2 指针变量和解引⽤操作符(*)

2.2.1 指针变量

在这里p就是指针变量,int*是指针变量类型,p变量里存放的是变量a的地址。

2.2.2 如何拆解指针类型

其实int* p理解为:int是p指针变量所指向的变量的类型。

              *理解为:告诉我们p是指针变量。

              p理解为:指针变量的名字。

如果是char类型的数据:

2.2.3 解引⽤操作符

我们得到了一个变量的地址,将他存在了一个指针变量中,我们这样做有什么用呢?

我们可以通过地址找到这个地址所指向的变量。来操作,改变它。我们必须要用到解引用操作符:*。

*pa=0;相当于通过pa中存放的地址找到了这个a变量,并把a赋值为0;

我们因为可以看到打印a与打印*pa的结果是一样的。

2.3 指针变量的⼤⼩

前⾯的内容我们了解到,32位机器假设有32根地址总线,每根地址线出来的电信号转换成数字信号后是1或者0,那我们把32根地址线产⽣的2进制序列当做⼀个地址,那么⼀个地址就是32个bit位,需要4个字节才能存储。
如果指针变量是⽤来存放地址的,那么指针变的⼤⼩就得是4个字节的空间才可以。
同理64位机器,假设有64根地址线,⼀个地址就是64个⼆进制位组成的⼆进制序列,存储起来就需要8个字节的空间,指针变的⼤⼩就是8个字节。

我们可以分别看一下在X86(32位)和X64(64位)下打印地址大小的结果:

32位下的结果:

64位下的结果:

可以看到在同一环境下不同类型的地址所占内存的大小是相同的,也就是说地址无贵贱,所占内存大小都遵循下面的规律:

32位平台下地址是32个bit位,指针变量⼤⼩是4个字节
64位平台下地址是64个bit位,指针变量⼤⼩是8个字节
注意指针变量的⼤⼩和类型是⽆关的,只要指针类型的变量,在相同的平台下,⼤⼩都是相同的。

3. 指针变量类型的意义

3.1 指针的解引⽤

代码一:

代码二:

代码一是将int*类型强制类型转变成了char*类型,解引用时只访问了一个字节将44变成了00

而代码二int*类型的pi解引用访问了四个字节,将n全变为0;

结论:指针的类型决定了,对指针解引⽤的时候有多⼤的权限(⼀次能操作⼏个字节)。
⽐如: char* 的指针解引⽤就只能访问⼀个字节,⽽ int* 的指针的解引⽤就能访问四个字节。

3.2 指针+-整数

我们可以看出, char* 类型的指针变量+1跳过1个字节, int* 类型的指针变量+1跳过了4个字节。
这就是指针变量的类型差异带来的变化。
结论:指针的类型决定了指针向前或者向后⾛⼀步有多⼤(距离)。

3.3 void* 指针

在指针类型中有⼀种特殊的类型是 void* 类型的,可以理解为⽆具体类型的指针(或者叫泛型指
针),这种类型的指针可以⽤来接受任意类型地址。但是也有局限性, void* 类型的指针不能直接进⾏指针的+-整数和解引⽤的运算。
举例:
将⼀个int类型的变量的地址赋值给⼀个char*类型的指针变量。编译器给出了⼀个警
告,是因为类型不兼容。⽽使⽤void*类型就不会有这样的问题。
但是void*并不是万能的:
这⾥我们可以看到, void* 类型的指针可以接收不同类型的地址,但是⽆法直接进⾏指针运算。
那么 void* 类型的指针到底有什么⽤呢?这里有一篇博客可以参考,使用在了函数传参上面
(C语言)qsort函数模拟实现: http://t.csdnimg.cn/FMB3k

4. const修饰指针

4.1 const修饰变量

变量是可以修改的,如果把变量的地址交给⼀个指针变量,通过指针变量的也可以修改这个变量。
但是如果我们希望⼀个变量加上⼀些限制,不能被修改,怎么做呢?这就是const的作⽤
上面代码中m被const修饰了不能再被修改了,
但是如果我们绕过m直接通过地址去修改m也是可以的。
我们可以看到这⾥⼀个确实修改了,但是我们还是要思考⼀下,为什么m要被const修饰呢?就是为了不能被修改,如果p拿到m的地址就能修改m,这样就打破了const的限制,这和我们的想法是不一样的,所以应该让p拿到m的地址也不能修改m,那接下来怎么做呢?

4.2 const修饰指针变量

总结: const修饰指针变量的时候
const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。
但是指针变量本⾝的内容可变。
const如果放在*的右边,修饰的是指针变量本⾝,保证了指针变量的内容不能修改,但是指针指
向的内容,可以通过指针改变。

5. 指针运算

指针的基本运算有三种,分别是:
指针+- 整数
指针-指针
指针的关系运算

5.1 指针+- 整数

因为数组在内存中是连续存放的,只要知道第⼀个元素的地址,顺藤摸⽠就能找到后⾯的所有元素。
我们通过运用地址访问了数组中所有的元素,并打印出来。

5.2 指针-指针

5.3 指针的关系运算

C语言中指针的知识多而复杂,可能有的地方写的不明白,欢迎在评论区讨论。
感谢观看,感谢指正错误。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智能指纹密码储物柜的设计

目 录 摘 要 II Abstract III 引 言 1 1 总体方案设计 3 1.1 设计要求 3 1.2 方案比较与论证 3 2 硬件介绍和设计 5 2.1 单片机及最小系统 5 2.2 液晶显示模块 6 2.3 按键控制部分电路 7 2.4 指纹模块 8 2.5 继电器模块 9 3 系统软件设计 10 3.1 系统程序工作分析 10 3.2 主程…

FPGA高端项目:FPGA基于GS2971的SDI视频接收+OSD动态字符叠加,提供1套工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐本博已有的 SDI 编解码方案本方案的SDI接收转HDMI输出应用本方案的SDI接收图像缩放应用本方案的SDI接收纯verilog图像缩放纯verilog多路视频拼接应用本方案的SDI接收HLS图像缩放HLS多路视频拼接应用本方案的SDI接收HLS多路视频融合叠加应用…

maven archetype 项目原型

拓展阅读 maven 包管理平台-01-maven 入门介绍 Maven、Gradle、Ant、Ivy、Bazel 和 SBT 的详细对比表格 maven 包管理平台-02-windows 安装配置 mac 安装配置 maven 包管理平台-03-maven project maven 项目的创建入门 maven 包管理平台-04-maven archetype 项目原型 ma…

c++ primer学习笔记(二)

目录 第三章 一、命名空间的using声明 二、标准库的string类型 1、string对象的定义和初始化 2、string对象的读写 3、string对象的操作 4、string对象中字符的处理 三、标准库的vector类型 1、vector对象的定义和初始化 2、vector对象的操作 四、迭代器简介 1、简…

阿里云ECS u1实例2核4G,5M固定带宽80G ESSD Entry盘价格199元一年

阿里云ECS u1实例2核4G,5M固定带宽 80G ESSD Entry盘199元一年,购买条件为企业用户,新用户和老用户都可以,但必须是企业用户,如果是个人实名认证,可以升级为企业认证再购买,ECS通用算力型u1实例…

顶顶通呼叫中心中间件-机器人话术如何实现在放音期间不接收按键信息

文章目录 前言联系我们实现方法 前言 场景:进入机器人话术时,在话术放音期间不接收用户的按键信息,等话术放音完成后才允许接收用户的按钮信息,然后根据用户的按钮信息执行相应的机器人话术流程。 联系我们 有意向了解呼叫中心中…

第一节 JDBC是什么?

JDBC代表Java数据库连接(Java Database Connectivity),它是用于Java编程语言和数据库之间的数据库无关连接的标准Java API,换句话说:JDBC是用于在Java语言编程中与数据库连接的API。 JDBC库包括通常与数据库使用相关,如下面提到的…

史称GPT-4最强劲敌——Claude 3 大模型它来了【附体验教程】

Anthropic 的 Claude 3 Sonnet 模型现已在亚马逊云科技的 Amazon Bedrock 正式可用。 Amazon Bedrock 是目前 第一个 也是 唯一 一个提供 Claude 3 Sonnet 的托管服务 。 Claude 3 免费测试体验者福利🧧:https://mp.weixin.qq.com/s/hszLRa8B5zKsTDg2bmI…

C#,入门教程(06)——解决方案资源管理器,代码文件与文件夹的管理工具

上一篇: C#,入门教程(05)——Visual Studio 2022源程序(源代码)自动排版的功能动画图示https://blog.csdn.net/beijinghorn/article/details/124675293 大家平时都怎么管理源代码与文件夹呢?世界上最好的集成开发环境…

varchar类型字段为什么经常定义成255

MySQL | ver < 4.1&#xff1a; VARCHAR以字节为单位存储&#xff0c;所以假设全部为常用汉字&#xff08;UTF-8 3字节编码长度&#xff09;&#xff0c;则VARCHAR(255)共可存放约85个汉字&#xff1b; MySQL | ver > 4.1&#xff1a; VARCHAR以字符为单位存储&#x…

对于网络IO的理解

网络IO理解 首先服务端将本机地址和端口bind在listensock上&#xff0c;再用listen()去将listensock套接字设置为listen状态&#xff0c;然后调用accept&#xff0c;进入阻塞状态。如果此时有客户端请求连接&#xff0c;就是第一次握手的开始。 客户端会先调用connect来申请连…

牛客网 华为机试 提前不重复的整数

本题要求提取不重复的整数&#xff0c;然后倒序输出&#xff0c;我们可以采用hashset来存储结果&#xff0c;这样就能避免重复。 为了从右往左获取数字&#xff0c;我们可以把这个数对10取余&#xff0c;得到的余数就是其每一位的数。然后我们把得到的数字添加到hashset中&…

#QT(MP3播放器-部分界面)

1.IDE&#xff1a;QTCreator 2.实验&#xff1a;制作一个mps播放器&#xff0c;界面可以实现鼠标拖动 3.记录&#xff1a; &#xff08;1&#xff09;network网络多线程 &#xff08;2&#xff09;Http &#xff08;3&#xff09;QJsonObject封装JSON对象 &#xff08;4&am…

c语言-大小写字母的转换

目录 方法一&#xff1a;库函数直接转换 1、toupper的测试代码 2、tolower的测试代码 方法二&#xff1a;通过修改ASCII码值转换 1、自己实现大写转小写 2、自己实现小写转大写 结语 前言&#xff1a; 在使用c语言写代码时&#xff0c;通常会遇到很多将大小写字母相互…

性能测试总结 —— 测试流程篇!

本文主要介绍下性能测试的基本流程&#xff0c;性能测试从实际执行层面来看&#xff0c;测试的过程一般分为这么几个阶段&#xff0c;如下图&#xff1a;       下面分别介绍下每个阶段具体需要做什么&#xff1a; 一、性能需求分析&#xff1a; 性能需求分析是整个性能…

从零学习Linux操作系统 第三十部分 部署Anisble

一、ansible实验环境的部署 主控机 更改服务器主机名 hostnamectl set-hostname westos_ansible.westos.org 主服务器需要能够实现上网 修改网卡使之能够上网 能ping通 代表可以连接外网 搭载本地软件仓库 并且挂载镜像 装载 dnf install httpd -y 让其开机启动并且…

C语言指针的初步认识--学习笔记(3)

1. 字符指针变量 在C语言中&#xff0c;字符串通常被视为字符数组&#xff0c;但它们可以有不同的表示方式。字符指针变量存储的是字符串的地址。这意味着&#xff0c;当你有一个字符串时&#xff0c;你可以通过改变字符指针的值来改变这个字符串&#xff0c;因为你实际上改变的…

C++_位图

目录 1、位图的使用 2、位图实现 3、位图与哈希表的区别 4、位图的应用 结语 前言&#xff1a; 位图采用的是哈希表的思想&#xff0c;哈希表的映射层面是在字节上&#xff0c;而位图的映射层面就是在bit位上。由于bit位所能展现的信息无非只有‘1’和‘0’&#xff0c;所…

LeetCode 热题 100 (尽量ACM模式刷) 持续更新!!!

LeetCode 热题 100 哈希hash 1 两数之和 /** 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出和为目标值target的那两个整数&#xff0c;并返回它们的数组下标。* 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案…

项目管理必备:进度报告撰写指南!

本文将探讨如何将进度报告写作整合到你的工作流程中&#xff0c;包括确定最适合的报告时间、编写方法和与团队一起构建报告结构的建议。最后&#xff0c;还会分享一些撰写进度报告的最佳做法&#xff0c;助你掌握这种对工作有巨大帮助的方法。 什么是进度报告&#xff1f; 它…