指针(上)--指针存放,数组指针及const的了解

本文从指针的起源开始,介绍了指针如何存放变量和内存布局,包括指针变量、指针的指针和数组中的指针。同时深入探讨了const在C语言中的作用和使用,包括const变量的声明、含义和使用场景,帮助读者理解const常量在编译和运行阶段的不同行为。最后总结了const修饰指针的各种情况及其含义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 之前一直听别人说指针是如何如何难,导致在写代码时一直对指针是诚惶诚恐。现在,是时候应该系统地学一下指针了,既然怕为什么不去克服,不去克服又怎么提高,不管是否困难。事实证明指针也没什么好怕的,只要掌握调用逻辑,使用时多个心眼,相信我们都能熟练精准地使用。
 下面我们开始指针的理解之旅,这篇文章我将从指针的”起源”开始说起,以便有一个阶段性的了解。
 同样借鉴了以下几篇文章,写得很详细,具体可以转以下链接进行更深入的了解,同时如果有什么不对的地方烦请及时告知。
彻底搞定C语言指针详解-完整版-时候初学者-必备
C指针,C语言中的指针详解
c语言指针学习
C语言数组与指针详解
 下面开始正文。

指针与内存

 我们在学习指针的过程中不只一次地看见人们会把指针比喻成门牌号,比喻成电影院座位,这些比喻不可否认都很好的将指针抽象到了生活中,方便我们的理解,当然我们也可以借鉴这种方法来理解生活中那些让我们一时琢磨不透的知识。

内存怎么放变量

 先上一张图,以便后续讲解。
这里写图片描述

变量?

 首先知道下变量是什么意思,怎么出现的?
 从上图可以看出来,内存地址中6至7存储了一个值为10,12中存储了一个’x’。当然实际中的内存地址通常不会这么浅显地为6,为12,他可能是一长串的值,比如0x7fff8b6a378c这样的值,如果就是用这种值来对我们需要的值进行访问和处理无疑将加重我们的负担,所以高级语言特性之一中就提供了通过名字而不是地址来访问内存,进行对内存的读与写。
 就如上图中虚线框出的i为值10的内存地址,c为字符值’x’的内存地址,这里的i和c我们可以称之为变量。如此再配上我们的贴近实际作用的变量名,比如currentTime,recvbuf等等就能给我们的编程和后续的代码阅读提供很大的方便。
 那么我们又不经要问这些变量又是谁将他们转变成类似0x7fff8b6a378c这样的地址的呢?===>是由编译器为我们实现的。即如“变量=====>编译器=====>具体地址”的流程。

变量在内存中的存放

 而由上图可知:
 1、内存中一个单位空间占一个字节,并且这些空间连续;
 2、在内存中整型变量占4个字节,字符型变量占1个字节;
 3、变量会根据其自身大小在内存中占用适合自身大小的空间。

内存怎么放指针变量

 开始前先区别一下指针和地址,指针是存储地址一个变量,地址是内存分配。指针可以指向一个地址,也可以指向其他地址。
 指针变量是一个用于指向内存中的地址。那么这个指针的值,也就是地址在内存中是怎么放的呢?
 首先需要清楚的是,指针变量也是一个变量,只不过这个变量能存放一个内存的地址,程序中可以通过这个地址来找到对应地址的内容罢了。
 清楚了指针变量是一个变量,那么他在内存中的存放也是如下图所示:
这里写图片描述
 同时应该清楚32位系统中指针变量在内存中所占的长度为4个字节,所以上图中的指针变量p_i占用了内存中的13~16位置,保存的是6,即变量i的起始地址。
 需要了解的是指针变量所存储的指向一个变量的地址是否是一个该指针指向的变量的起始地址是由编译器决定的。也就是说上图中如果指针变量p_i是变量i的地址,那么他的值是否是6由编译器决定,一般的编译器是以第一个地址编号为指针变量的值。
 所以图中,p_i为变量i的地址,(*p_i)能访问到i的值,&i的值与p_i的值相等。

指针的指针

 有了上面的了解,对于指针的指针的理解也就轻松许多了,通用如下图:
这里写图片描述
 图中又命名了一个变量pp_i,他的值为13,这里的13我们可以看成一个普通的值,当然也可以看成我们现在需要讲的指针地址,可以发现如果将pp_i看成一个指针,那么他指向的内容即为指针p_i的地址,而p_i又是i的地址。所以我们可以这样说:
 p_i值是i的指针&

在 C++ 中,可以通过指针访问对象数组的数据。以下是详细的说明以及实现方法。 ### 如何通过指针访问对象数组 当创建一个对象数组时,可以使用指向该类型的指针来遍历并操作这些对象。假设有一个类 `MyClass` 和其对应的对象数组: #### 定义类和对象数组 ```cpp class MyClass { public: int value; void display() const { std::cout << "Value: " << value << std::endl; } }; int main() { const int size = 5; // 数组大小 MyClass objArray[size]; // 创建对象数组 // 初始化对象数组中的数据 for (int i = 0; i < size; ++i) { objArray[i].value = i * 10; } // 使用指针访问对象数组 MyClass* ptr = objArray; // 将指针初始化为数组首地址 for (int i = 0; i < size; ++i, ++ptr) { // 遍历数组 (*ptr).display(); // 或者写成 ptr->display(); } return 0; } ``` 上述代码展示了如何利用指针访问对象数组的内容,并调用成员函数显示每个对象的状态。注意,在这里我们既可以使用解引用运算符 `(*ptr)` 来访问成员变量或函数,也可以更简洁地使用箭头运算符 `ptr->`[^1]。 ### 结合PTA7-3题目背景的应用扩展 如果按照 PTA 的风格设计一道类似的题目,则可能涉及如下需求:给定一组自定义类型的数据结构存储于动态分配的对象数组中,请编写程序完成特定查询功能。下面给出基于此思路的一个例子——统计满足条件的目标数量并打印它们的信息。 #### 示例代码片段 ```cpp #include <iostream> using namespace std; // 假设这是我们要处理的简单学生记录模型 struct Student { string name; double score; bool passed() const {return score >= 60;} }; void processStudents(Student students[], int count){ cout<<"Passed Students:"<<endl; Student *pStudent = students; while(pStudent - students < count ){ if( pStudent ->passed()){ cout<<pStudent->name<<"\t"<<pStudent->score<<endl; } ++pStudent ; } } int main(){ int numStu; cin>>numStu; Student stuList[numStu]; for(auto &stu : stuList){ cin>>stu.name>>stu.score; } processStudents(stuList,numStu); return 0; } ``` 这段代码实现了对学生列表的操作,其中包含了通过指针迭代整个数组的过程[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值