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

1. 内存和地址

在了解指针前,我们需要知道内存和地址是什么。

1.1 内存

首先来看内存。举个例子:当你在酒店找房间时,你并不是一层一层一间一间找,而是通过酒店为每间房子设置的门牌号直接找到你的房间,这样的效率就会快很多。

把上面的例子投影到计算机中:CPU在处理数据的时候,需要在内存中取数据,处理后的数据又会放回到内存中。内存空间管理时就会把内存划分为一个个内存单元,每个内存单元大小设置为一字节。每个内存单元也有其相应的编号,这样CPU就可以通过编号快速找到一个内存单元。这个编号在计算机中我们称它为地址 。C语言中给地址起了个新的名字,叫指针 。因此我们可以理解为:内存单元的编号==地址==指针

1.2 如何理解编址

首先,需要知道,计算机内部是有很多硬件单元的,各个硬件单元相互工作时是通过"线"连接起来的。而CPU和内存之间也是有⼤量的数据交互的,所 以,两者必须也⽤线连起来。我们今天只关心地址总线(还有数据总线和控制总线)。当CPU在访问某个内存单元时,必须知道该内存单元在哪个位置,因此需要给每个内存单元进行编址。

计算机中的编址,并不是把每个字节的地址记录 下来,⽽是通过硬件设计完成的。就像吉他和钢琴等乐器一样,琴弦和钢琴键上并没有标注 do、re、mi......。但是演奏者总能精准地找到在什么位置,这是大家约定俗成的。

硬件编制也是如此,32位机器就有32根地址总线,每一位都有 0 和 1 两种结果,32根像就能表示出 2 的 32 次方种结果,每一种排列都表示一个地址,64位机器以此类推。地址信息被下达给内存,在内存上,就可以找到 该地址对应的数据,将数据在通过数据总线传⼊ CPU内寄存器。

2.指针变量和地址

2.1 取地址操作符(&)

在C语言中创建变量的本质就是向内存申请空间。如图:

右下角的内存中 & 为取地址操作符,图中为取出 x 的地址,是一个单目操作符。我们之前学的 a&b 表示 a 按位与 b ,两者不一样。上述代码就是创建了一个整型变量 x ,在内存中申请了 4 个字节用来存放 4。当我们打印 x 的地址时,就会发现这个内存单元中正好存放的是 4。

2.2 指针变量和解引用操作符

2.2.1指针变量

我们通过取地址操作符(&)得到一个变量的地址,我们通过指针变量将它存放起来,便于使用例如:

复制代码
#include <stdio.h>
int main()
{
    int x = 4;
    int * p = &x;//取出x的地址放到指针变量p中
    return 0;
}

指针变量也是一种变量,只不过让它是用来存放地址的,变量中的值都是地址。

2.2.2 如何理解指针变量

刚刚的定义的 int * p 中,* 说明 p 是一个指针变量,int 表示 p 指向的的类型是整型。同理如果有个 char、double、等类型的变量,他们的地址就要分别放在 char*、double* 中。

2.2.3 解引用操作符

我们将地址存起来肯定是要使用的,使用时我们就会用到解引用操作符(*)。

上图中就使用了解引用操作符我们通过 *p 找到了 x 并且修改了 x 的值,我们修改时并没有写 x = 0 ,而是直接通过指针变量来修改,即 *p=0 ,这样写代码时会更加灵活。

2.3 指针变量的大小

32位机器有32根地址总线,那么它就需要 4 个字节来存储地址(1个字节 8 个比特位,4个字节刚好 32 个比特位),同理 64 位机器则需要 8 个字节来存储地址。同时我们要注意**指针变量的大小和类型是无关的,只要指针类型的变量,在相同的平台下,大小都是相同的。**不管指针变量是 char 还是 int ,他们在32位机器下都是 4 个字节,在 64 位机器下都是 8 个字节。

3.指针变量类型的意义

3.1指针的解引用

让我们来对比下面两段代码:

我们发现 int* 和 char* 修改的字节不同,因此:指针的类型决定了对指针解引用的时候有多大的权限(⼀次能操作⼏个字节)。 ⽐如 char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引⽤就能访问四个字节。

3.2 指针+-整数

同样的,对指针+-时,不同的指针变量的类型所移动的距离也不同。若对 int* 进行+/-1时,会一次移动四个字节,而对 char* 进行+/-1时则一次移动一个字节。

3.3 void*指针

void* 表示无具体类型的指针。这种类型的指针可以接受任意类型的地址,但是我们不能直接对这种类型的指针进行+/-整数和对指针的解引用,需要进行强制类型转换。⼀般 void* 类型的指针是使⽤在函数参数的部分,⽤来接收不同类型数据的地址,这样的设计可以实现泛型编程的效果。使得⼀个函数来处理多种类型的数据。

4.指针运算

4.1 指针+-整数

数组在内存中是连续存放的,因此只要知道第⼀个元素的地址后,我们可以通过加减操作来获取后面的所有元素。

4.2 指针-指针

由图可得,指针-指针所得带的结果是两个指针之间的元素个数,但前提是这两个指针指向的是同一块内存空间。

另外,指针也能进行关系运算。

相关推荐
m0_736927041 分钟前
Spring Boot自动配置与“约定大于配置“机制详解
java·开发语言·后端·spring
feiyangqingyun27 分钟前
Qt项目作品在苹果macos上编译运行效果/视频监控系统/物联网平台等
开发语言·qt·macos
你不是我我1 小时前
【Java 开发日记】我们来说一说 Redisson 的原理
java·开发语言
kk”1 小时前
C++ stack 和 queue
开发语言·c++
Matlab仿真实验室1 小时前
基于Matlab实现双目图计算深度图
开发语言·数码相机·matlab·双目图计算深度图
Word码1 小时前
[排序算法]希尔排序
c语言·数据结构·算法·排序算法
QT 小鲜肉2 小时前
【数据结构与算法基础】05. 栈详解(C++ 实战)
开发语言·数据结构·c++·笔记·学习·算法·学习方法
老K的Java兵器库2 小时前
Collections 工具类 15 个常用方法源码:sort、binarySearch、reverse、shuffle、unmodifiableXxx
java·开发语言·哈希算法
武子康2 小时前
Java-153 深入浅出 MongoDB 全面的适用场景分析与选型指南 场景应用指南
java·开发语言·数据库·mongodb·性能优化·系统架构·nosql
rit84324992 小时前
ES6 箭头函数:告别 `this` 的困扰
开发语言·javascript·es6