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

发布于:2025-07-23 ⋅ 阅读:(12) ⋅ 点赞:(0)

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

        

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

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

        


网站公告

今日签到

点亮在社区的每一天
去签到