首页 > 其他分享 >深入理解指针(1)

深入理解指针(1)

时间:2024-11-01 17:45:57浏览次数:3  
标签:变量 32 地址 理解 深入 内存 指针 字节

1:内存和地址

1:内存

我们知道计算机上面的CPU在处理数据时,需要的数据是在内存中读取的,处理后的数据也会放回内存中,那我们买电脑时,电脑内存是8GB/16GB/32GB等,那这些内存空间如何高效管理呢?

其实也是内存划分为一个个的内存单元,每个内存的大小取1个字节。

一个bit(比特)位可以储存一个二进制的0或1;

一个Byte(字节)可以储存8个比特位。

然后往上是1kb=1024Byte,

MB,GB,TB,PB

2:地址

我们知道了内存的贮存方式,地址就是给一个个内存,取的一个编号,这些编号也叫做地址,也叫做指针。

内存单元的编号==地址==指针

3:正确理解编址

CPU访问内存中的某个字节空间,必须知道这个字节空间在内存的什么位置,⽽因为内存中字节很多,所以需要给内存进⾏编址。
计算机中的编址,并不是把每个字节的地址记录下来,⽽是通过硬件设计完成的。
钢琴、吉他 上⾯没有写上“剁、来、咪、发、唆、拉、西”这样的信息,但演奏者照样能够准确找到每⼀个琴弦每⼀个位置,这是为何?因为制造商已经在乐器硬件层⾯上设计好了,并且所有的演奏者都知道。本质是⼀种约定出来的共识!

⾸先,必须理解,计算机内是有很多的硬件单元,⽽硬件单元是要互相协同⼯作的。所谓的协同,⾄少相互之间要能够进⾏数据传递。
但是硬件与硬件之间是互相独⽴的,那么如何通信呢?答案很简单,⽤"线"连起来。
⽽CPU和内存之间也是有⼤量的数据交互的,所以,两者必须也⽤线连起来。
不过,我们今天关⼼⼀组线,叫做地址总线。
硬件编址也是如此
我们可以简单理解,32位机器有32根地址总线,每根线只有两态,表⽰0,1【电脉冲有⽆】,那么⼀根线,就能表⽰2种含义,2根线就能表⽰4种含义,依次类推。32根地址线,就能表⽰2^32种含义,每⼀种含义都代表⼀个地址。
地址信息被下达给内存,在内存上,就可以找到该地址对应的数据,将数据在通过数据总线传⼊CPU内寄存器

2:指针变量和地址

1:&取地址操作符

理解了内存和地址的关系,我们就需要知道,在C语言中创建变量,本质上是在向内存申请空间,比如:

f09b498c9d6642bbbd8f82456b0aa647.png

 c1feadeedcb54722be49068d5b875c5f.png

如果我们使用printf函数把a的地址打印出来,则会打印出 0x006FFD70 这个最小的地址 ,&a取出来的是a所占4个字节中最小的字节的地址。

虽然整型变量占用四个字节,我们只需要知道第一个字节的地址,我们就可以推出后面a的地址。

2:指针变量和解引用操作符*

1:指针变量

如果我们通过&操作符拿到了一个数据的地址,我们如何存放这个数据的地址呢,那就可以将地址放入指针变量中。

比如47f82cc721804e789bf99a4c78970d4e.png

指针变量也是一种变量,这种变量是专门来存储地址的,存放在指针变量中的值,会被默认理解为地址 

2:如何拆解指针类型

我们看到上述代码中pa的类型是int*,*是在说明pa是一个指针变量,而前面的int是在说明pa指向的是整型(int)类型的对象。

以此类推,char类型的变量,就存在char*类型的指针变量中。

3:解引用操作符

我们将地址保存起来后,我们应该如何使用它呢?

这个时候我们就需要引入解引用操作符*

如下

6194cb35541a4018ace594cc9abec064.png

 上⾯代码就使⽤了解引⽤操作符, *pa 的意思就是通过pa中存放的地址,找到指向的空间,
*pa其实就是a变量了;所以*pa = 0,这个操作符是把a改成了0.
有同学肯定在想,这⾥如果⽬的就是把a改成0的话,写成 a = 0; 不就完了,为啥⾮要使⽤指针呢?
其实这⾥是把a的修改交给了pa来操作,这样对a的修改,就多了⼀种的途径,写代码就会更加灵活,后期慢慢就能理解了。

3:指针变量的大小

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

4:指针变量的意义

调试我们可以看到,代码1会将n的4个字节全部改为0,但是代码2只是将n的第⼀个字节改为0。 结论:指针的类型决定了,对指针解引用的时候有多⼤的权限(⼀次能操作几个字节)。 比如: char* 的指针解引⽤就只能访问⼀个字节,而 int* 的指针的解引用就能访问四个字节。 注意: 指针的类型决定了指针向前或者向后⾛⼀步有多大(距离)。

5:void指针

在指针类型中有⼀种特殊的类型是 void * 类型的,可以理解为无具体类型的指针(或者叫泛型指 针),这种类型的指针可以⽤来接受任意类型地址。 但是也有局限性, void* 类型的指针不能直接进行指针的+-整数和解引用的运算。

比如用于函数中。

3:const修饰变量

变量是可以修改的,如果把变量的地址交给⼀个指针变量,通过指针变量的也可以修改这个变量。 但是如果我们希望⼀个变量加上⼀些限制,不能被修改,怎么做呢?这就是const的作⽤。

例如

上面代码中,m可被修改,n不可被修改。

但是如果在指针层面上那么n值就可以被修改。

4:const修饰指针变量

在上面const修饰变量中,可以从指针层面上可以修改变量。

但是我们也可以在指针层面上,将指针用const修改,这样避免了全部可以修改变量的方式。

直接说结论

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

5:指针运算

指针运算有三类:

指针+- 整数 指针-指针 指针的关系运算

6:野指针(野狗)

野指针是什么?

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

1:野指针的成因

1:指针没初始化

指针没初始化,指针指向的空间就是未知的

2:指针越界访问

3:指针指向的空间释放

比如在主函数中用指针变量,储存子函数中某个数的地址。

2:如何避免野指针

1:指针初始化

2:避免指针越界
3:指针变量不再使⽤时,及时置NULL,指针使用之前检查有效性
4:避免返回局部变量的地址
当指针变量指向⼀块区域的时候, 比特就业课主页:https://m.cctalk.com/inst/s9yewhfr 我们可以通过指针访问该区域,后期不再使⽤这个指针访问空间的 时候,我们可以把该指针置为NULL。 因为约定俗成的⼀个规则就是:只要是NULL指针就不去访问, 同时使⽤指针之前可以判断指针是否为NULL。 我们可以把野指针想象成野狗,野狗放任不管是⾮常危险的,所以我们可以找⼀棵树把野狗拴来, 就相对安全了,给指针变量及时赋值为NULL,其实就类似把野狗栓起来,就是把野指针暂时管理起来。 不过野狗即使拴起来我们也要绕着⾛,不能去挑逗野狗,有点危险;对于指针也是,在使⽤之前,我 们也要判断是否为NULL,看看是不是被拴起来起来的野狗,如果是不能直接使⽤,如果不是我们再去使⽤。

7:assert断言

转载一下

https://blog.csdn.net/weixin_45031801/article/details/136882008

标签:变量,32,地址,理解,深入,内存,指针,字节
From: https://blog.csdn.net/2403_87752060/article/details/143415448

相关文章

  • 有Redis为什么还要本地缓存?谈谈你对本地缓存的理解?
    本地缓存是将数据存储在应用程序所在的本地内存中的缓存方式。既然,已经有了Redis可以实现分布式缓存了,为什么还需要本地缓存呢?接下来,我们一起来看。为什么需要本地缓存?尽管已经有Redis缓存了,但本地缓存也是非常有必要的,因为它有以下优点:速度优势:本地缓存直接利用本地内存,......
  • 单链表题+数组题(快慢指针和左右指针)
    @目录说明:本文章用于“单链表题+数组题”“链表”知识一、案例说明(使用快慢指针)问题1.1判断链表是否有环问题1.2:已知链表有环,请返回这个环的起点位置问题1.3:寻找无环单链表的中点,要求:如果偶数个数以左面一个节点为中点问题1.4:寻找无环单链表的中点,要求:如果偶数个数以右面一个节......
  • WebSocket详解:从前端到后端的全栈理解
    文章目录前言一、WebSocket简介1.1WebSocket的特点二、WebSocket的工作原理2.1握手过程2.2数据传输三、WebSocket在前端的应用四、WebSocket在后端的应用五、WebSocket的局限与解决方案结语前言随着互联网技术的发展,传统的HTTP协议在某些场景下的局限性逐渐显......
  • 深入解析:JWT Bearer 认证在 .NET Core 中的应用
    在现代Web应用中,安全认证是确保用户数据和系统安全的重要一环。JSONWebToken(JWT)是一种流行的认证方式,它可以在客户端和服务端之间安全地传递信息。本文将详细介绍JWTBearer认证的概念、工作原理、在.NETCore中的实现步骤,以及最佳实践。一、什么是JWT?JSONWebTok......
  • 【C++】string 类模拟实现:深入探索字符串操作原理
     快来参与讨论......
  • C语言中指针和数组的相互关系
    在C语言中,指针和数组有着紧密的相互关系。数组是数据的集合,而指针则是一个包含内存地址的变量。指针可以用来访问数组的元素,便于高效的内存访问和操作。更具体来说,数组名本身就是一个指向首元素的指针、通过指针运算,我们可以遍历数组的每个元素、数组和指针的索引操作是等价的、......
  • 论企业集成平台的理解与应用
    一、引言随着企业信息化建设的不断深入,企业在生产、管理和服务等各方面产生了大量的数据和应用系统。然而,不同系统间的数据孤岛问题,以及信息整合和协同操作的需求日益增加,使得企业集成平台(EnterpriseIntegrationPlatform,EIP)成为信息化建设中的关键基础设施。EIP作为一种......
  • 智能指针使用
    普通指针的不足new和new[]的内存需要用delete和deletel]释放。程序员的主观失误,忘了或漏了释放。程序员也不确定何时释放。普通指针的释放类内的指针,在析构函数中释放。C++内置数据类型,如何释放?new出来的类,本身如何释放?C++11新增三个智能指针类型unique_pt......
  • 【C++】智能指针的正确使用方式
    本文将从这几方面讲解智能指针:智能指针的应用场景分析智能指针的性能分析:为什么shared_ptr性能比unique_ptr差指针作为函数参数时应该传,传值、传引用,还是裸指针?对于智能指针的使用,实际上是对所有权和生命周期的思考1.unique_ptr:专属所有权1.1unique_ptr介绍我们大......
  • 深入浅出:AutoMapper 的使用与最佳实践
    在现代软件开发中,特别是在.NET环境中,数据传输对象(DTO)与实体模型之间的映射是一个常见的需求。AutoMapper是一个强大的库,可以简化这一过程,减少样板代码,提高开发效率。本文将详细讲解AutoMapper的基本概念、各种用法以及最佳实践。什么是AutoMapper?AutoMapper是一个对象到......