【017】C++ 指针变量详解:内存访问的奥秘

引言


💡 作者简介:专注分享高性能服务器后台开发技术知识,涵盖多个领域,包括C/C++、Linux、网络协议、设计模式、中间件、云原生、数据库、分布式架构等。目标是通过理论与代码实践的结合,让世界上看似难以掌握的技术变得易于理解与掌握。公众号《Lion 莱恩呀》。
👉
🎖️ CSDN实力新星、专家博主,阿里云博客专家、华为云云享专家
👉
🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、高级编程;掌握各个知识点。
👉
🔔 专栏地址:C++从零开始到精通
👉
🔔 博客主页:https://blog.csdn.net/Long_xu


🔔 上一篇:【016】C++预处理详解(内存分区、变量的存储、头文件、宏等)
🔔 下一篇:【018】C++的指针数组和数组指针

一、内存概述

对于32位平台的进程,其内存空间大小限制为4GB(2的32次方),其中1GB是操作系统保留的虚拟地址空间。因此,32位进程最多只能使用3GB的内存空间。

而对于64位平台的进程,其内存空间大小限制高达16EB(2的64次方),实际上远远超过了目前可用的物理内存容量。这意味着64位进程可以利用更多的内存资源来提高应用程序性能和响应速度。

在这里插入图片描述
系统为内存的每一个字节分配32 bit / 64 bit 的地址编码(虚拟地址),这个编号称为地址。

无论任何类型的地址,都是存储单元的编号,在32位平台上永远占4字节,在64位平台上永远占8字节。

在这里插入图片描述
取地址得到的是首地址。

二、指针变量

2.1、地址和指针变量的关系

地址就是内存的地址编号。
指针变量本质上是变量,只是该变量保存的是内存的地址编号,而不是普通数值。
在这里插入图片描述

2.2、定义指针变量

格式:

<类型名> *<变量名>;

示例:

int *data;
short *data;
long data;
double data;
char *data;
float *data;

无论任何类型的指针变量,在32位平台上永远占4字节,在64位平台上永远占8字节。

指针变量和普通变量间建立关系:

int num;
int *p;
p=&num;//取地址,p指向num
*p=10;//取内容、内容赋值

2.3、指针变量的初始化

指针变量在操作前必须指向合法的地址空间。
(1)指针变量如果不初始化,立即操作会出现段错误。
(2)指针变量如果没有指向合法的空间,建议初始化为nullptrNULL。不要操作指向nullptrNULL的指针变量。
(3)将指针变量初始化为合法的地址:变量地址、动态申请的地址、函数入口地址等。

int num;
int *p=NULL;
p=&num;

2.4、指针类型

(1)指针变量自身的类型:把变量名去掉,剩下的就是指针类型。

int num;
int *p;//指针类型为int *
// p是指针变量
p=&num;
// 使用时,&和*相遇,从右往左依次匹配。
*&p==p;

(2)指针变量指向的类型。

int *p;//p指向的类型是int

(3)指针变量的指向类型决定取值宽度。
在这里插入图片描述
(4)指针变量的指向类型决定了 +1 跨度。
在这里插入图片描述
(5)*p等价于num

int num=0;
int* p=&num;
// *p == num

2.5、案例

在这里插入图片描述

int num=0x01020304;

案例一,取出0x0102的值:

short *p=(short *)&num;
short get=*(p+1);

案例二,取出0x02的值:

char *p=(char *)&num;
char get=*(p+2);

案例三,取出0x0203的值:

char *p=(char *)&num;
short get=*(short *)(p+1);

2.6、注意事项

(1)void不能定义普通变量。因为系统无法计算void的大小,无法开辟空间。
(2)void* 可以定义指针变量,因为系统知道指针变量永远是4字节或8字节。此时的指针变量就是万能的一级指针变量,能保存任意一级指针的地址编码。万能指针一般用于函数的形参,达到算法操作多种数据类型的目的。

int num=0;
void *p=&num;

short num2=10;
p=&num2;

注意,不要直接对void * 的指针变量取 *,如果一定要对void * 的指针变量取值 *,就必须强转才行。

int num=0;
void *p=&num;

cout<<(int *)p<<endl;

(3)指针变量未初始化不能取 *
(4)指针变量初始化为NULLnullptr,也不能取 *
(5)指针变量不要越界访问。

char ch=0;
int *p=&ch;//越界

char *p2=&ch;
p2++;//越界

在这里插入图片描述

三、数组元素的指针

3.1、概述

数组元素的指针是指向数组中单个元素的内存地址。在C和C++语言中,数组名可以被解释为指向数组第一个元素的指针,也就是说,它包含了该数组的内存地址。

要访问数组中的特定元素,可以使用下标运算符[]来访问它们。例如,如果a是一个整型数组,则a[0]表示第一个元素,a[1]表示第二个元素,以此类推。

可以通过将其加上偏移量来获取任何给定元素的地址。例如,&a[2]表示第三个元素(假设数组从零开始编号),因为它是从第一个元素开始的两个整数位置。

通过使用指向特定元素的指针变量来引用该元素,可以对其进行操作。例如,在C语言中,以下代码将把第三个元素设置为10:

int a[5];
int *p = &a[2];
*p = 10;

此时,p指向a[2](即第三个)并将其值更改为10。

数组元素的指针变量和数组名等价:
在这里插入图片描述

3.2、在使用中 [ ] 就是 *()的缩写

int arr[]={1,2,3,4,5};
cout<<"arr[1]="<<arr[1]<<endl;		// 输出2
cout<<"*(arr+1)="<<*(arr+1)<<endl;	// 输出2

cout<<"*(1+arr)="<<*(1+arr)<<endl;	// 输出2
cout<<"1[arr]="<<1[arr]<<endl;		// 输出2
// 

[]*()的缩写,[]左边的值放在+的左边,[]里面的值放在+右边,整体取 *

分析为什么arr == &arr[0]

&arr[0]==&*(arr+0)==arr+0==arr。

示例:

int arr[]={1,2,3,4,5};
int *p=arr+3;


p[-1]=arr+3-1=arr+2=3
p[1]=arr+3+1=arr+4=5

3.3、指向同一数组的元素的两个指针变量间的关系

  1. 两个指针变量相减,等于它们的元素个数。
  2. 两指针变量赋值,则它们指向同一处。
  3. 两指针变量判断相等,用于判断它们是否指向同一处。
  4. 两指针变量判断大小(>、<、>=、<=、!=),用于判断它们的位置关系。
  5. 两指针变量不能相加,相加是无意义的。

四、字符串与指针

4.1、字符数组

char *str1[128]="hello world";

str1是字符数组,开辟128字节存放字符串"hello world"。sizeof(str1)是128。
在这里插入图片描述

4.2、字符串指针变量

char *str2="hello world";

这个代码的含义是将字符串的首地址赋给str2sizeof(str2)是4或8。注意与字符数组的区别。
在这里插入图片描述
注意:不能给字符串指针变量赋值,会报错误,因为文字常量区不能赋值。

str2[3]='F';//错误的,引发异常

五、总结

C++ 中的指针变量是一个特殊类型的变量,它存储了另一个变量的地址。在使用指针变量时,需要注意以下几点:

  1. 指针的声明:声明一个指针需要使用星号(*)运算符,并在其前面加上数据类型。例如:int *ptr;

  2. 取地址运算符 &:取地址运算符 & 可以用于获取一个变量的内存地址。例如:int num = 5; int *ptr = &num;

  3. 解引用运算符 *:解引用运算符 * 用于访问指针所指向的实际值。例如:int num = 5; int *ptr = &num; cout << "Value of num is: " << *ptr;

  4. 动态内存分配:动态内存分配允许程序在运行时请求操作系统分配内存。使用 new 关键字来分配内存,并使用 delete 关键字释放已经分配的内存。

  5. 空指针检查:空指针是未初始化或者被设置为 null 的指针。在使用空指针时需要进行检查,以避免程序崩溃或者出现其他问题。

在这里插入图片描述

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lion Long

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值