1.起因
今天在看CPlusPlusThings时看到的关于const使用的一个代码:
void func(const int var); // 传递过来的参数不可变
void func(int *const var); // 指针本身不可变
传递过来的参数及指针本身在函数内不可变,无意义!
表明参数在函数体内不能被修改,但此处没有任何意义,var本身就是形参,在函数内不会改变。包括传入的形参是指针也是一样。
输入参数采用“值传递”,由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加const 修饰。
2.思考
const位于*号后时,表示指针指向的对象不能改变,且不能指向一个常量。
1.形参指针是实参的拷贝
我一开始以为把指针作为参数,作用类似于引用,既可以修改所指向的地址,也可以修改指向对象的值。但实际上,指针作为参数的时候,仍是一个传值,将变量的地址传入函数,我们可以修改指向的值,不能修改指向的对象。
看下面代码:
#include <stdio.h>
#include <stdlib.h>
void F(int *pi)
{
pi = (int *)malloc(sizeof(int));
}
main()
{
int *pi = NULL;
F(pi);
printf("%d/n", pi == NULL);
最后的返回值是1. 即使传入了指针,还是不能保留改变的结果。
原因是,传递给形参的指针,会产生一个实参的拷贝,这个拷贝跟实参指向相同,所以我们能通过传递指针的方式改变原指针指向的值。
实例
void swap(int *p,int *q)
{
int *r=q;
*q=*p;
*q=*r;
}
int main()
{
int a=5,b=4;
int *p=a,*q=b;
swap(p,q);
}
2.为什么不能修改原指针指向的对象
先看个例子:
#include <stdio.h>
#include <stdlib.h>
int f(int *q)
{
int a = 10;
q = (int*)malloc(sizeof(int));
*q = a;
return 0;
}
int main()
{
int *p = NULL;
f(p);
printf("%d", *p);
return 0;
}
这个程序会崩溃。p仍旧是NULL,无法返回值。
因为传递指针会产生拷贝,而这个拷贝的指针和实参,实际上是两个不同的变量,证明如下。
#include <iostream>
int f(int *q)
{
std::cout << &q << std::endl;
return 0;
}
int main()
{
int a = 10;
int *p = &a;
f(p);
std::cout << &p;
return 0;
}
结果:
所以,虽然拷贝的指针和实参是指向的同一个地址,但却是两个不同的指针,在对形参指向的对象做改变的时候,不会影响到实参。
3.总结
可以理解成两个指向同一地址的指针,你可以通过这两个指针修改这个地址上的值,却不能只通过修改一个指针的指向就改变另一个的指向。
所以关于一开始的代码。
void func(int *const var); // 指针本身不可变
是无意义的,跟
void func(int *var)
起一样的作用。因为指针本身就不会改变。
参考资料1:指针变量也是传值调用的(C语言)!作者:RiderOnStorm
参考资料2:C语言中的地址传递(传指针,传递给形参的指针仍然是实参指针的一份拷贝)作者:踏樰无痕丶zz(链接里有怎么通过二级指针解决不能修改指向对象的方法)