首页 » 网站建设 » php指针应用技能技巧_10分钟掌握C措辞指针

php指针应用技能技巧_10分钟掌握C措辞指针

访客 2024-12-10 0

扫一扫用手机浏览

文章目录 [+]

在讲指针之前,我们先来理解下变量在「内存」中是如何存放的。

在程序中定义一个变量,那么在程序编译的过程中,系统会根据你定义变量的类型来分配「相应尺寸」的内存空间。
那么如果要利用这个变量,只须要用变量名去访问即可。

php指针应用技能技巧_10分钟掌握C措辞指针

通过变量名来访问变量,是一种「相对安全」的办法。
由于只有你定义了它,你才能够访问相应的变量。
这便是对内存的基本认知。
但是,如果光知道这一点的话,实在你还是不知道内存是如何存放变量的,由于底层是如何事情的,你依旧不清楚。

php指针应用技能技巧_10分钟掌握C措辞指针
(图片来自网络侵删)

那么如果要连续穷究的话,你就须要把变量在内存中真正的样子是什么搞清楚。
内存的最小索引单元是1字节,那么你实在可以把内存比作一个超级大的「字符型数组」。
在上一节我们讲过,数组是有下标的,我们是通过数组名和下标来访问数组中的元素。
那么内存也是一样,只不过我们给它起了个新名字:地址
每个地址可以存放「1字节」的数据,以是如果我们须要定义一个整型变量,就须要霸占4个内存单元。

那么,看到这里你可能就明白了:其实在程序运行的过程中,完备不须要变量名的参与。
变量名只是方便我们进行代码的编写和阅读,只有程序员和编译器知道这个东西的存在。
而编译器还知道详细的变量名对应的「内存地址」,这个是我们不知道的,因此编译器就像一个桥梁。
当读取某一个变量的时候,编译器就会找到变量名所对应的地址,读取对应的值。

初识指针和指针变量

那么我们现在就来切入正题,指针是个什么东西呢?

所谓指针,便是内存地址(下文简称地址)。
C措辞中设立了专门的「指针变量」来存储指针,和「普通变量」不一样的是,指针变量存储的是「地址」。

定义指针

指针变量也有类型,实际上取决于地址指向的值的类型。
那么如何定义指针变量呢:

很大略:类型名 指针变量名

char pa;//定义一个字符变量的指针,名称为paint pb;//定义一个整型变量的指针,名称为pbfloat pc;//定义一个浮点型变量的指针,名称为pc

把稳,指针变量一定要和指向的变量的类型一样,不然类型不同可能在内存中所占的位置不同,如果定义错了就可能导致出错。

取地址运算符和取值运算符

获取某个变量的地址,利用取地址运算符&,如:

char pa = &a;int pb = &f;

如果反过来,你要访问指针变量指向的数据,那么你就要利用取值运算符,如:

printf(\"大众%c, %d\n\"大众, pa, pb);

这里你可能创造,定义指针的时候也利用了,这里属于符号的「重用」,也便是说这种符号在不同的地方就有不同的用意:在定义的时候表示「定义一个指针变量」,在其他的时候则用来「获取指针变量指向的变量的值」。

直接通过变量名来访问变量的值称之为直接访问,通过指针这样的形式访问称之为间接访问,因此取值运算符有时候也成为「间接运算符」。

比如:

//Example 01//代码来源于网络,非个人原创#include <stdio.h>intmain(void){char a = 'f';int f = 123;char pa = &a;int pf = &f;printf(\公众a = %c\n\"大众, pa);printf(\公众f = %d\n\公众, pf);pa = 'c';pf += 1;printf(\"大众now, a = %c\n\"大众, pa);printf(\公众now, f = %d\n\公众, pf);printf(\"大众sizeof pa = %d\n\公众, sizeof(pa));printf(\"大众sizeof pf = %d\n\"大众, sizeof(pf));printf(\"大众the addr of a is: %p\n\公众, pa);printf(\公众the addr of f is: %p\n\"大众, pf);return 0;}

程序实现如下:

//Consequence 01a = ff = 123now, a = cnow, f = 124sizeof pa = 4sizeof pf = 4the addr of a is: 00EFF97Fthe addr of f is: 00EFF970

避免访问未初始化的指针

void f{int a;a = 10;}

像这样的代码是十分危险的。
由于指针a到底指向哪里,我们不知道。
就和访问未初始化的普通变量一样,会返回一个「随机值」。
但是如果是在指针里面,那么就有可能覆盖到「其他的内存区域」,乃至可能是系统正在利用的「关键区域」,十分危险。
不过这种情形,系统一样平常会驳回程序的运行,此时程序会被「中止」并「报错」。
假如万一中奖的话,覆盖到一个合法的地址,那么接下来的赋值就会导致一些有用的数据被「莫名其妙地修正」,这样的bug是十分不好排查的,因此利用指针的时候一定要把稳初始化。

指针和数组

有些读者可能会有些奇怪,指针和数组又有什么关系?这俩货明明八竿子打不着井水不犯河水。
别焦急,接着往下看,你的不雅观点有可能会改变。

数组的地址

我们刚刚说了,指针实际上便是变量在「内存中的地址」,那么如果有细心的小伙伴就可能会想到,像数组这样的一大摞变量的凑集,它的地址是啥呢?

我们知道,从标准输入流中读取一个值到变量中,用的是scanf函数,一样平常貌似在后面都要加上&,这个实在便是我们刚刚说的「取地址运算符」。
如果你存储的位置是指针变量的话,那就不须要。

//Example 02intmain(void){int a;int p = &a;printf(\"大众请输入一个整数:\公众);scanf(\"大众%d\"大众, &a);//此处须要&printf(\"大众a = %d\n\公众, a);printf(\"大众请再输入一个整数:\"大众);scanf(\"大众%d\公众, p);//此处不须要&printf(\公众a = %d\n\"大众, a);return 0;}

程序运行如下:

//Consequence 02请输入一个整数:1a = 1请再输入一个整数:2a = 2

在普通变量读取的时候,程序须要知道这个变量在内存中的地址,因此须要&来取地址完成这个任务。
而对付指针变量来说,本身便是「其余一个」普通变量的「地址信息」,因此直接给出指针的值就可以了。

试想一下,我们在利用scanf函数的时候,是不是也有不须要利用&的时候?便是在读取「字符串」的时候:

//Example 03#include <stdio.h>intmain(void){char url[100];url[99] = '\0';printf(\"大众请输入TechZone的域名:\"大众);scanf(\"大众%s\公众, url);//此处也不用&printf(\"大众你输入的域名是:%s\n\公众, url);return 0;}

程序实行如下:

//Consequence 03请输入TechZone的域名:www.techzone.ltd你输入的域名是:www.techzone.ltd

因此很好推理:数组名实在便是一个「地址信息」,实际上便是数组「第一个元素的地址」。
咱们试试把第一个元素的地址和数组的地址做个比拟就知道了:

//Example 03 V2#include <stdio.h>intmain(void){char url[100];printf(\"大众请输入TechZone的域名:\公众);url[99] = '\0';scanf(\公众%s\"大众, url);printf(\"大众你输入的域名是:%s\n\"大众, url);printf(\"大众url的地址为:%p\n\公众, url);printf(\公众url[0]的地址为:%p\n\"大众, &url[0]);if (url == &url[0]){printf(\"大众两者同等!
\"大众);}else{printf(\公众两者不一致!
\公众);}return 0;}

程序运行结果为:

//Comsequense 03 V2请输入TechZone的域名:www.techzone.ltd你输入的域名是:www.techzone.ltdurl的地址为:0063F804url[0]的地址为:0063F804两者同等!

这么看,该当是实锤了。
那么数组后面的元素也便是依次今后放置,有兴趣的也可以自己写代码考试测验把它们输出看看。

指向数组的指针

刚刚我们验证了数组的地址便是数组第一个元素的地址。
那么指向数组的指针自然也就有两种定义的方法:

...char p;//方法1p = a;//方法2p = &a[0];

指针的运算

当指针指向数组元素的时候,可以对指针变量进行「加减」运算,+n表示指向p指针所指向的元素的「下n个元素」,-n表示指向p指针所指向的元素的「上n个元素」。
并不是将地址加1。

如:

//Example 04#include <stdio.h>intmain(void){int a = { 1,2,3,4,5 };int p = a;printf(\"大众p = %d, (p+1) = %d, (p+2) = %d\n\"大众, p, (p + 1), (p + 2));printf(\"大众p -> %p, (p+1) -> %p, (p+2) -> %p\n\"大众, p, p + 1, p + 2);return 0;}

实行结果如下:

//Consequence 04p = 1, (p+1) = 2, (p+2) = 3p -> 00AFF838, (p+1) -> 00AFF83C, (p+2) -> 00AFF840

有的小伙伴可能会想,编译器是怎么知道访问下一个元素而不是地址直接加1呢?

实在就在我们定义指针变量的时候,就已经见告编译器了。
如果我们定义的是整型数组的指针,那么指针加1,实际上便是加上一个sizeof(int)的间隔。
相对付标准的下标访问,利用指针来间接访问数组元素的方法叫做指针法

实在利用指针法来访问数组的元素,不一定须要定义一个指向数组的单独的指针变量,由于数组名自身便是指向数组「第一个元素」的指针,因此指针法可以直接浸染于数组名:

...printf(\"大众p -> %p, p+1 -> %p, p+2 -> %p\n\公众, a, a+1, a+2);printf(\"大众a = %d, a+1 = %d, a+2 = %d\"大众, a, (a+1), (a+2));...

实行结果如下:

p -> 00AFF838, p+1 -> 00AFF83C, p+2 -> 00AFF840b = 1, b+1 = 2, b+2 = 3

现在你是不是觉得,数组和指针有点像了呢?不过笔者先提醒,数组和指针虽然非常像,但是绝对「不是」一种东西。

乃至你还可以直接用指针来定义字符串,然后用下标法来读取每一个元素:

//Example 05//代码来源于网络#include <stdio.h>#include <string.h>intmain(void){char str = \公众I love TechZone!\公众;int i, length;length = strlen(str);for (i = 0; i < length, i++){printf(\公众%c\"大众, str[i]);}printf(\"大众\n\公众);return 0;}

程序运行如下:

//Consequence 05I love TechZone!

在刚刚的代码里面,我们定义了一个「字符指针」变量,并且初始化成指向一个字符串。
后来的操作,不仅在它身上可以利用「字符串处理函数」,还可以用「下标法」访问字符串中的每一个字符。

当然,循环部分这样写也是没毛病的:

...for (i = 0, i < length, i++){printf(\"大众%c\"大众, (str + i));}

这就相称于利用了指针法来读取。

指针和数组的差异

刚刚说了许多指针和数组相互更换的例子,可能有的小伙伴又开始说:“这俩货不便是一个东西吗?”

随着你对指针和数组越来越理解,你会创造,C措辞的创始人不会这么无聊去创建两种一样的东西,还叫上不同的名字。
指针和数组究竟是「不一样」的。

比如笔者之前看过的一个例子:

//Example 06//代码来源于网络#include <stdio.h>intmain(void){char str = \"大众I love TechZone!\"大众;int count = 0;while (str++ != '\0'){count++;}printf(\"大众统共有%d个字符。
\n\"大众, count);return 0;}

当编译器报错的时候,你可能会开始疑惑你学了假的C措辞语法:

//Error in Example 06缺点(活动)E0137表达式必须是可修正的左值缺点C2105“++”须要左值

我们知道,str++ != ‘\0’是一个复合表达式,那么就要遵照「运算符优先级」来看。
详细可以回顾《C措辞运算符优先级及ASCII对照表》。

str++str的优先级「更高」,但是自增运算符要在「下一条语句」的时候才能生效。
以是这个语句的理解便是,先取出str所指向的值,判断是否为\0,若是,则跳出循环,然后str指向下一个字符的位置。

看上去貌似没啥毛病,但是,看看编译器见告我们的东西:表达式必须是可修正的左值

++的操为难刁难象是str,那么str到底是不是「左值」呢?

如果是左值的话,那么就必须知足左值的条件。

拥有用于识别和定位一个存储位置的标识符

存储值可修正

第一点,数组名str是可以知足的,由于数组名实际上便是定位数组第一个元素的位置。
但是第二点就不知足了,数组名实际上是一个地址,地址是「不可以」修正的,它是一个常量。
如果非要利用上面的思路来实现的话,可以将代码改成这样:

//Example 06 V2//代码来源于网络#include <stdio.h>intmain(void){char str = \"大众I love TechZone!\"大众;char target = str;int count = 0;while (target++ != '\0'){count++;}printf(\"大众统共有%d个字符。
\n\公众, count);return 0;}

这样就可以正常实行了:

//Consequence 06 V2统共有16个字符。

这样我们就可以得出:数组名只是一个「地址」,而指针是一个「左值」。

指针数组?数组指针?

看下面的例子,你能分辨出哪个是指针数组,哪个是数组指针吗?

int p1[5];int(p2)[5];

单个的我们都可以判断,但是组合起来就有些难度了。

答案:

int p1[5];//指针数组int(p2)[5];//数组指针

我们挨个来剖析。

指针数组

数组下标的优先级是最高的,因此p1是一个有5个元素的「数组」。
那么这个数组的类型是什么呢?答案便是int,是「指向整型变量的指针」。
因此这是一个「指针数组」。

那么这样的数组该当怎么样去初始化呢?

你可以定义5个变量,然后挨个取地址来初始化。

不过这样太繁琐了,但是,并不是说指针数组就没什么用。

比如:

//Example 07#include <stdio.h>intmain(void){char p1[5] = {\公众人生苦短,我用Python。
\"大众,\公众PHP是天下上最好的措辞!
\"大众,\"大众One more thing...\"大众,\公众一个好的程序员该当是那种过单行线都要往两边看的人。
\公众,\"大众C措辞很随意马虎让你犯缺点;C++看起来好一些,但当你用它时,你会创造会去世的更惨。
\"大众};int i;for (i = 0; i < 5; i++){printf(\公众%s\n\公众, p1[i]);}return 0;}

结果如下:

//Consequence 07人生苦短,我用Python。
PHP是天下上最好的措辞!
One more thing...一个好的程序员该当是那种过单行线都要往两边看的人。
C措辞很随意马虎让你犯缺点;C++看起来好一些,但当你用它时,你会创造会去世的更惨。

这样是不是比二维数组来的更加直接更加普通呢?

数组指针

在优先级里面属于「同级」,那么就按照「先后顺序」进行。

int(p2)p2定义为「指针」, 后面跟随着一个5个元素的「数组」,p2就指向这个数组。
因此,数组指针是一个「指针」,它指向的是一个数组。

但是,如果想对数组指针初始化的时候,千万要小心,比如:

//Example 08#include <stdio.h>intmain(void){int(p2)[5] = {1, 2, 3, 4, 5};int i;for (i = 0; i < 5; i++){printf(\公众%d\n\"大众, (p2 + i));}return 0;}

Visual Studio 2019报出以下的缺点:

//Error and Warning in Example 08缺点(活动)E0146初始值设定项值太多缺点C2440“初始化”: 无法从“initializer list”转换为“int ()[5]”警告C4477“printf”: 格式字符串“%d”须要类型“int”的参数,但可变参数 1 拥有了类型“int ”

这实在是一个非常范例的缺点利用指针的案例,编译器提示说这里有一个「整数」赋值给「指针变量」的问题,由于p2归根结底还是指针,以是该当给它通报一个「地址」才行,变动一下:

//Example 08 V2#include <stdio.h>intmain(void){int temp[5] = {1, 2, 3, 4, 5};int(p2)[5] = temp;int i;for (i = 0; i < 5; i++){printf(\"大众%d\n\公众, (p2 + i));}return 0;}

//Error and Warning in Example 08 V2缺点(活动)E0144\"大众int \"大众 类型的值不能用于初始化 \"大众int ()[5]\"大众 类型的实体缺点C2440“初始化”: 无法从“int [5]”转换为“int ()[5]”警告C4477“printf”: 格式字符串“%d”须要类型“int”的参数,但可变参数 1 拥有了类型“int ”

可是怎么还是有问题呢?

我们回顾一下,指针是如何指向数组的。

int temp[5] = {1, 2, 3, 4, 5};int p = temp;

我们原来以为,指针p是指向数组的指针,但是实际上「并不是」。
仔细想想就会创造,这个指针实际上是指向的数组的「第一个元素」,而不是指向数组。
由于数组里面的元素在内存中都是挨着个儿存放的,因此只须要知道第一个元素的地址,就可以访问到后面的所有元素。

但是,这么来看的话,指针p指向的便是一个「整型变量」的指针,并不是指向「数组」的指针。
而刚刚我们用的数组指针,才是指向数组的指针。
因此,该当将「数组的地址」通报给数组指针,而不是将第一个元素的地址传入,只管它们值相同,但是「含义」确实不一样:

//Example 08 V3//Example 08 V2#include <stdio.h>intmain(void){int temp[5] = {1, 2, 3, 4, 5};int(p2)[5] = &temp;//此处取地址int i;for (i = 0; i < 5; i++){printf(\"大众%d\n\公众, (p2 + i));}return 0;}

程序运行如下:

//Consequence 0812345

指针和二维数组

在上一节《C措辞之数组》我们讲过「二维数组」的观点,并且我们也知道,C措辞的二维数组其实在内存中也是「线性存放」的。

假设我们定义了:int array[4][5]

array

array作为数组的名称,显然该当表示的是数组的「首地址」。
由于二维数组实际上便是一维数组的「线性拓展」,因此array该当便是指的指向包含5个元素的数组的指针

如果你用sizeof去测试arrayarray+1的话,就可以测试出来这样的结论。

(array+1)

首先从刚刚的问题我们可以得出,array+1同样也是指的指向包含5个元素的数组的指针,因此(array+1)便是相称于array[1],而这刚好相称于array[1][0]的数组名。
因此(array+1)便是指第二行子数组的第一个元素的地址。

((array+1)+2)

有了刚刚的结论,我们就不难推理出,这个实际上便是array[1][2]
是不是觉得非常大略呢?

总结一下,便是下面的这些结论,记住就好,理解那当然更好:

(array + i) == array[i]((array + i) + j) == array[i][j](((array + i) + j) + k) == array[i][j][k]...

数组指针和二维数组

我们在上一节里面讲过,在初始化二维数组的时候是可以偷

int array[3] = {{1, 2, 3},{4, 5, 6}};

刚刚我们又说过,定义一个数组指针是这样的:

int(p)[3];

那么组合起来是什么意思呢?

int(p)[3] = array;

通过刚刚的解释,我们可以知道,array是指向一个3个元素的数组的「指针」,以是这里完备可以将array的值赋值给p

实在C措辞的指针非常灵巧,同样的代码用不同的角度去解读,就可以有不同的运用。

那么如何利用指针来访问二维数组呢?没错,便是利用「数组指针」:

//Example 09#include <stdio.h>intmain(void){int array[3][4] = {{0, 1, 2, 3},{4, 5, 6, 7},{8, 9, 10, 11}};int(p)[4];int i, j;p = array;for (i = 0, i < 3, i++){for (j = 0, j < 4, j++){printf(\"大众%2d \"大众, ((p+i) + j));}printf(\"大众\n\"大众);}return 0;}

运行结果:

//Consequence 090 1 2 34 5 6 78 9 10 11

void指针

void实际上是无类型的意思。
如果你考试测验用它来定义一个变量,编译器肯定会「报错」,由于不同类型所占用的内存有可能「不一样」。
但是如果定义的是一个指针,那就没问题。
void类型中指针可以指向「任何一个类型」的数据,也便是说,任何类型的指针都可以赋值给void指针。

将任何类型的指针转换为void是没有问题的。
但是如果你要反过来,那就须要「逼迫类型转换」。
此外,不要对void指针「直接解引用」,由于编译器实在并不知道void指针会存放什么样的类型。

//Example 10#include <stdio.h>intmain(void){int num = 1024;int pi = &num;char ps = \公众TechZone\公众;void pv;pv = pi;printf(\公众pi:%p,pv:%p\n\"大众, pi, pv);printf(\公众pv:%d\n\公众, pv);pv = ps;printf(\公众ps:%p,pv:%p\n\公众, ps, pv);printf(\公众pv:%s\n\公众, pv);}

这样会报错:

//Error in Example 10缺点C2100造孽的间接寻址缺点C2100造孽的间接寻址

如果一定要这么做,那么可以用「逼迫类型转换」:

//Example 10 V2#include <stdio.h>intmain(void){int num = 1024;int pi = &num;char ps = \公众TechZone\"大众;void pv;pv = pi;printf(\"大众pi:%p,pv:%p\n\"大众, pi, pv);printf(\"大众pv:%d\n\"大众, (int)pv);pv = ps;printf(\公众ps:%p,pv:%p\n\"大众, ps, pv);printf(\公众pv:%s\n\公众, pv);}

当然,利用void指针一定要小心,由于void指针险些可以「通吃」所有类型,以是间接使得不同类型的指针转换变得合法,如果代码中存在不合理的转换,编译器也不会报错。

因此,void指针能不用则不用,后面讲函数的时候,还可以解锁更多新的玩法。

指针

在C措辞中,如果一个指针不指向任何数据,那么就称之为「空指针」,用「」来表示。
实在是一个宏定义:

#define ((void )0)

在大部分的操作系统中,地址0常日是一个「不被利用」的地址,以是如果一个指针指向,就意味着不指向任何东西。
为什么一个指针要指向呢?

实在这反而是一种比较指的推举的「编程风格」——当你暂时还不知道该指向哪儿的时候,就让它指向,往后不会有太多的麻烦,比如:

//Example 11#include <stdio.h>intmain(void){int p1;int p2 = ;printf(\"大众%d\n\"大众, p1);printf(\"大众%d\n\公众, p2);return 0;}

第一个指针未被初始化。
在有的编译器里面,这样未初始化的变量就会被授予「随机值」。
这样指针被称为「迷途指针」,「野指针」或者「悬空指针」。
如果后面的代码对这类指针解引用,而这个地址又刚好是合法的话,那么就会产生莫名其妙的结果,乃至导致程序的崩溃。
因此养成良好的习气,在暂时不清楚的情形下利用,可以节省大量的后期调试的韶光。

指向指针的指针

开始套娃了。
实在只要你理解了指针的观点,也就没什么大不了的。

//Example 12#include <stdio.h>intmain(void){int num = 1;int p = &num;int pp = &p;printf(\"大众num: %d\n\"大众, num);printf(\"大众p: %d\n\"大众, p);printf(\"大众p: %d\n\"大众, pp);printf(\公众&p: %p, pp: %p\n\"大众, &p, pp);printf(\公众&num: %p, p: %p, pp: %p\n\公众, &num, p, pp);return 0;}

程序结果如下:

//Consequence 12num: 1p: 1p: 1&p: 004FF960, pp: 004FF960&num: 004FF96C, p: 004FF96C, pp: 004FF96C

当然你也可以无限地套娃,一贯指下去。
不过这样会让代码可读性变得「很差」,过段韶光可能你自己都看不懂你写的代码了。

指针数组和指向指针的指针

那么,指向指针的指针有什么用呢?

它可不是为了去创造混乱代码,在一个经典的实例里面,就可以体会到它的用途:

char Books = {\公众《C专家编程》\"大众,\"大众《C和指针》\公众,\"大众《C的陷阱与毛病》\"大众,\"大众《C Primer Plus》\"大众,\"大众《Python根本教程(第三版)》\公众};

然后我们须要将这些书进行分类。
我们创造,个中有一本是写Python的,其他都是C措辞的。
这时候指向指针的指针就派上用场了。
首先,我们刚刚定义了一个指针数组,也便是说,里面的所有元素的类型「都是指针」,而数组名却又可以用指针的形式来「访问」,因此就可以利用「指向指针的指针」来指向指针数组:

...char Python;char CLang[4];Python = &Books[5];CLang[0] = &Books[0];CLang[1] = &Books[1];CLang[2] = &Books[2];CLang[3] = &Books[3];...

由于字符串的取地址值实际上便是其「首地址」,也便是一个「指向字符指针的指针」,以是可以这样赋值。

这样,我们就利用指向指针的指针完成了对书本的分类,这样既避免了摧残浪费蹂躏多余的内存,而且当个中的书名要修正,只须要改一次即可,代码的灵巧性和安全性都得到了提升。

常量和指针

常量,在我们目前的认知里面,该当是这样的:

520, 'a'

或者是这样的:

#define MAX 1000#define B 'b'

常量和变量最大的差异,便是前者「不能够被修正」,后者可以。
那么在C措辞中,可以将变量变成像具有常量一样的特性,利用const即可。

const int max = 1000;const char a = 'a';

const关键字的浸染下,变量就会「失落去」本来具有的可修正的特性,变成“只读”的属性。

指向常量的指针

强大的指针当然也是可以指向被const润色过的变量,但这就意味着「不能通过」指针来修正它所引用的值。
总结一下,便是以下4点:

指针可以修正为指向不同的变量

指针可以修正为指向不同的常量

可以通过解引用来读取指针指向的数据

不可以通过解引用来修正指针指向的数据

常量指针指向非常量的常量指针

指针本身作为一种「变量」,也是可以修正的。
因此,指针也是可以被const润色的,只不过位置稍稍「发生了点变革」:

...int const p = &num;...

这样的指针有如下的特性:

指针自身不能够被修正

指针指向的值可以被修正

指向常量的常量指针

在定义普通变量的时候也用const润色,就得到了这样的指针。
不过由于限定太多,一样平常很少用到:

...int num = 100;const int cnum = 200;const int const p = &cnum;...

http://www.techzone.ltd/post/CPointer/

标签:

相关文章

phprow指针技巧_简说C措辞数组指针的妙用

数组指针是一种分外的指针,它可以指向一个完全的数组,而不是单个的元素。数组指针的定义形式为:类型名 (指针名 [长度];例如:in...

网站建设 2024-12-11 阅读0 评论0