C/C++指针踩坑历险记-常量指针-const ptr *,指针常量ptr * const,引用,指针传参,指针修改,指针指向的值修改等问题
Posted --believe
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C/C++指针踩坑历险记-常量指针-const ptr *,指针常量ptr * const,引用,指针传参,指针修改,指针指向的值修改等问题相关的知识,希望对你有一定的参考价值。
C/C++指针踩坑历险记-常量指针-const ptr *,指针常量ptr * const,引用,指针传参,指针修改,指针指向的值修改等问题
好久没写C语言了,不过一直用C++在刷题,遇到指针总有些发憷?初学指针的时候觉得指针好难,其实搞清指针的重要几个概念,指针就不难~对指针一些重点知识进行一个总结。
指针初体验
我们知道指针本质上就是一个存放地址的变量(该变量存放地址,一串你看不懂的数字)。比如
int a = 3;
int* ptr = &a;//就表示指向a的一个变量ptr,ptr内部存放的是一个地址(一串你看不懂的数字)
下面举个例子,直观地展示一下ptr的值
#include<stdio.h>
#include<stdlib.h>
int main()
int a = 3;
int* ptr = &a;//ptr是一个地址
printf("0x%x", ptr);//打印ptr的值
输出结果
通过设置断点查看程序执行过程,也可以查看ptr存放的到底是什么
你现在只需要知道指针就是指向一个内存块的地址,本质上就是一个变量。
对指针有了直观的认识之后,你肯定会想,要一个内存单元的地址有什么用呢?这个地址(0x00d3fb30)我又看不懂。我们要内存中的值(比如上面a的值3)不就行了吗?
其实不然,指针在函数参数传递中大有妙用。请往下看
指针在函数"传值"中的应用
我们知道函数传参过程中,实参和形参结合,也就是形参会等于实参的值,然后函数老大就一脚把实参踹开,之后就不干实参啥事了。
之后在函数内部,函数老大就抓着形参不放,所有的操作都是对实参起作用,和形参无关(暂时这么理解)。下面举个例子
#include<stdio.h>
#include<stdlib.h>
void add(int a)
a = a + 1;
printf("函数内部的a值(形参)为%d\\n", a);//形式结合,a=b=3,然后a=a+1=4.
int main()
int b = 3;
add(b);
printf("函数外部的b值(实参)为%d\\n", b);//实参不变,b=3
通过这个例子,我们要记住,函数形参和实参结合时,函数内部先将实参的值赋给形参,然后再对形参进行操作。
当形参为地址时,对形参操作也可能会影响实参,下面举例说明
#include<stdio.h>
#include<stdlib.h>
void add(int* a) //形参为指针,a等于b的地址
*a = *a + 1;//a也就是b的地址,*表示取出该地址内存中的值3,加1后存放在a地址中。即3+1=4
printf("函数内部的a地址为0x%x\\n", a);//一个地址,和b的地址一样0x136f9c4
printf("函数内部的a地址内存里面的值为%d\\n", *a);//4
int main()
int b = 3;
add(&b);
printf("函数外部的b的地址为0x%x\\n", &b);//b的地址0x136f9c4
printf("函数外部的b值(实参)为%d\\n", b);//在函数内部通过地址改变了b的值,b=4
运行结果
通过这个地址我们需要明白两点
-
当函数形参为指针类型时,表示该函数传递一个指针给形参,然后对形参进行操作。此时形参是一个指针,也就是一个地址,我们通过地址可以使实参发生变化。比如例子中改变*a使得实参b发生变化。示意图如下:
-
为了和传值区分,我们称上面函数传参方式为传址。其实传址本质上还是传值。
传址妙用
传址可以大大减少内存的消耗,试想一下如果b中存放的是一个占很大内存的对象,如果采用传值方式传递,形实结合会新开辟一块和b一样的空间,供函数内部操作。这样会很消耗内存空间。
但如果我们只传递b的一个地址(一串数字的大小),形实结合时,仅仅需要一小块空间就能够存放下b的地址。然后在函数内仅仅需要通过*就可以操作该地址内部的值。此举大大节约空间。但此举操作可能会影响函数外部的对象的值,使用时应该考虑清楚。
用*对指针指向的值修改
毫无疑问,在函数内部用*对形参指向的值进行修改,函数外部的实参值也会变化。如下
#include<stdio.h>
#include<stdlib.h>
void add(int* a) //形参为指针,a等于b的地址
*a = *a + 1;//a也就是b的地址,*表示取出该地址内存中的值3,加1后存放在a地址中。即3+1=4
printf("函数内部的a地址为0x%x\\n", a);//一个地址,和b的地址一样0x136f9c4
printf("函数内部的a地址内存里面的值为%d\\n", *a);//4
int main()
int b = 3;
add(&b);
printf("函数外部的b的地址为0x%x\\n", &b);//b的地址0x136f9c4
printf("函数外部的b值(实参)为%d\\n", b);//在函数内部通过地址改变了b的值,b=4
但是如果直接对形参修改(不用*),不会对函数外部的实参值有任何影响。如下
直接对指针本身修改
#include<stdio.h>
#include<stdlib.h>
void add(int* a) //形参为指针
int c = 10;
a = &c;//a的值变化了,此时a已经与函数外部的b彻底没关系了。不会影响函数外部b的值。
printf("函数内部的a地址为0x%x\\n", a);//a为c的地址
printf("函数内部的a地址内存里面的值为%d\\n", *a);//*a=10
int main()
int b = 3;
add(&b);
printf("函数外部的b的地址为0x%x\\n", &b);//b的地址
printf("函数外部的b值(实参)为%d\\n", b);//b=3,未发生变化
要正确理解 * 表示对该指针指向的内存单元的值进行操作。
直接对形参修改(不用*),表示对该地址修改了。原来形参还和实参指向同一块地址,形参地址一旦修改,形参就彻底和实参失去联系了。再对形参任何操作均不会对函数外部的实参值有任何影响。这点要注意,容易出错。
常量指针
所谓常量指针就是指向常量的指针,表示为const int*
。不能用*去修改内存中的常量。举例
#include<stdio.h>
#include<stdlib.h>
int main()
int a = 3;
const int* ptr = &a;
*ptr = 4;//报错:表达式必须是可修改的左值
指针常量
指针常量,表示该地址是一个常量,不能修改。表示为int * const
.举例
#include<stdio.h>
#include<stdlib.h>
int main()
int a = 3;
int b = 4;
int* const ptr= &a;
ptr = &b;//报错:表达式必须是可修改的左值
C++中的引用,本质上就是指针常量。
C++引用
C++引用是C++中特有的,本质上就是指针常量,如果进行修改,一定是指向的内存变化,而不是指针本身。用&表示。在引用的基础上改变,原值也要变,可以看做一个变量的别名。举例
#include<stdio.h>
#include<stdlib.h>
int main()
int a = 3;
int& ptr= a;//ptr就是a的别名
printf("%d\\n", ptr);//3
ptr = 5;
printf("%d\\n", ptr);//5
printf("%d\\n", a);//5
以上是关于C/C++指针踩坑历险记-常量指针-const ptr *,指针常量ptr * const,引用,指针传参,指针修改,指针指向的值修改等问题的主要内容,如果未能解决你的问题,请参考以下文章