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 指针-指针

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

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

相关推荐
q***25120 分钟前
java进阶1——JVM
java·开发语言·jvm
望眼欲穿的程序猿20 分钟前
Win系统Vscode+CoNan+Cmake实现调试与构建
c语言·c++·后端
while(1){yan}21 分钟前
线程的状态
java·开发语言·jvm
豐儀麟阁贵24 分钟前
8.3 Java常见的异常类
java·开发语言
lzh2004091929 分钟前
【C++STL】List详解
开发语言·c++
q***448132 分钟前
Java进阶10 IO流
java·开发语言
济宁雪人38 分钟前
Java安全基础——文件系统安全
java·开发语言·安全
Charles_go39 分钟前
C#中级46、什么是模拟
开发语言·oracle·c#
20岁30年经验的码农42 分钟前
Java RabbitMQ 实战指南
java·开发语言·python
星轨初途1 小时前
数据结构排序算法详解(2)——选择排序(附动图)
c语言·数据结构·经验分享·笔记·b树·算法·排序算法