c语言 指针_C语言——指针

6203fdfcdfbda19327a4835a170db6b4.png

学习阶段:高中信竞、大学编程。

前置知识:二进制与十六进制,C语言基础,数组。

指针初学可能比较难理解,我这篇文章尽量用通俗易懂的方式来讲解。

1. 指针概述

为什么有指针这个东西?因为指针很贴近计算机内部的实际工作原理,与内存实际的寻址方式类似。C语言可以说是高级语言中最贴近机器的语言,而像Python、JavaScript这种更亲和于人类的语言与机器的关系则比较远了,甚至它们本身可能还是用C语言写出来的呢。

指针可以形象地比喻为在内存中定位的导航员。内存那么大,怎么知道我需要的东西存在哪里呢?可以让指针来记录与导航。我们先来了解一下内存。

2. 预备知识

2.1 内存

研究过组装机、电脑配件的话,一定知道内存条这个东西。现在这个时代,一台家用电脑的内存一般是2GB、4GB、8GB、16GB、32GB、64GB等等。

把CPU比作干活的人,则内存就相当于工作台。CPU在跑的程序以及很多相关数据都存在内存内,这就相当于人在干活时要把相关资料放在工作台上使用。

内存可以看成是一个巨大的数组,我这里记为

memory[0..n]

memory的每一个单元存1B=8bit,memory[0]就是内存的第一个单元。这个中括号里面的数,即数组下标,被称为内存地址,简称为地址。我确定了一个地址,也就相当于确定了内存中的一个单元。

通常,我们说的32位机器,意思就是地址是32bit的,最大支持的内存是

memory[0x00000000..0xFFFFFFFF]

最小地址是0,最大地址是0xFFFFFFFF=2^32-1,最大支持

也就是说32位机器理论上最大支持4GB的内存,这就是它逐渐被淘汰的原因。

而64位机器理论上最大支持的内存是

这个量级远大于目前的需求,因此128位机器在相当长的时间内不会出现。

2.2 变量与数据类型

C语言有很多数据类型,不同的数据类型在内存中的占用空间存储格式也不一样。不同数据类型的存储格式比较复杂,这里不详述。我只谈谈不同的占用空间。

一个变量在内存中占用都是连续空间,记T类型的变量在内存中占用sizeof(T)字节的空间。当我声明一个T类型的变量a时,内存会寻找连续且可用的sizeof(T)个单元,把它们分配给变量a,比如说是memory[100..103]这4B的空间。此后我对变量a进行读写,也就相当于对memory[100..103]这4B的空间进行读写。

某些数据类型的占用空间:short短整形占用2B,int整形占用4B;float浮点形占用4B,double双浮点型占用8B;char字符型占用1B.

3. 指针

指针是一种特殊的数据类型,指针类型的变量应存储的是内存地址。在32位机器上,任何一个内存地址都是32bit=4B,故任何一个指针型变量都占用4B.

现在问题来了,指针指向内存中的一个单元,我怎么知道这个单元里面存的是什么东西,是什么类型的数据?因此,在声明指针变量的时候,也要声明这个指针指向数据的类型,比如int型指针、char型指针等。

3.1 指针的声明

在语法上,声明指针类型使用*符号,例如

int *a, b, *c; //a和c是指针,b不是指针
char *ch;

这两句代码声明了int*型的变量acint型变量b以及char*型变量ch. 根据语法,我们习惯上称T型指针为T*型,含义就是T*型变量是指针,其所指的相关内存单元存的是T型数据。 (注意,这里的b变量不是指针,仅仅为普通的int整形。)

3.2 指针的使用

指针有很多种使用方式,包括动态申请内存、函数地址传参等等。我这里仅介绍最简单的使用方式。我提供一份例程,可直接从例程中学习指针的声明与使用。

例程:

int x=1, y=2; //声明x与y并赋初值
int *p=&x; //声明p且p指向x
*p=11; //p修改x
p=&y; //p指向y
*p=12; //p修改y
printf("x=%d, y=%d", x, y); //打印x与y

第一行,在内存中申请连续的4B区域存入int型数据1,记为变量x;再在内存中申请连续的4B区域存入int型数据2,记为变量y. 假设x对应内存区域memory[100..103]y对应内存区域memory[200..203]. 第一行执行完毕,内存如图1所示:

70914f530c286c08a31bb7d6600a69f4.png
图1 第一行执行完毕

第二行, 在内存中申请连续的4B区域存入int*型地址数据100,记为变量p. 这里&符号是取地址运算符,表示取变量x的首地址,在本例中就是100. 这一行代码是声明指针同时赋初值,相当于以下两行代码:

int *p;
p=&x;

第二行执行完毕,内存如图2所示(100的十六进制是0x64):

6e5903c2529a953edcf9be500a19dc74.png
图2 第二行执行完毕

第三行,将p所指的地址起4B空间内存入int型数据11. 这里*解地址运算符, 表示取得指针所指的内存空间。 第三行执行完毕,内存如图3所示:

a7da7fead77b593ebc235d6be6902541.png
图3 第三行执行完毕

如果第三行改为执行p=(int*)11;,则是先把int型数据11强制转换为int*型数据11,然后赋值给p,如图3.2所示:

3259a4327f33ce4a040c8093c4cf1b4c.png
图3.2 第三行改为执行p=(int*)11;

此时p所指的内存空间不一定是可用的。因此像这样直接给指针赋值一个常数的情况非常罕见。

第四行,py的首地址。第四行执行完毕,内存如图4所示:

146a2393887ff53e50e17f148bd537b4.png
图4 第四行执行完毕

第五行,把变量y的值改为12. 第五行执行完毕,内存如图5所示:

308089d9562ccf14c308f46ee9c3566f.png
图5 第五行执行完毕

第六行,打印xy的值,打印结果应为:

x=11, y=12

4. 多级指针

指针也可以指向指针,称为多级指针。

例程:

int x=1;
int *p=&x;
int **p2=&p;

这里p2就是一个二级指针,它的类型是int**,它也存了一个地址,但是这个地址是某个int*型变量的地址,在这里是存了int*型变量p的地址。

假设x的首地址是0x10,p的首地址是0x20,那么内存的情况如图6所示:

f0f1e1e6d9e5a8dc35614e92ad5af54f.png
图6 多级指针示例

三级、四级等等更多级的指针也是存在的,但是几乎不会用到。二级指针一般只在二维数组中会用到,其他情况也很少见。尽量不要使用多级指针,不然真的容易弄晕自己。

5. 答疑

5.1 星号*的不同作用

在指针声明、数据类型中,*表示是指针类型;在已声明变量前面的*是解地址运算符,比如说*p就是用p的内容求得其所指的区域;当然,*还有算数乘法等含义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值