C中最可怕的东西莫过于指针,指来指去就乱了…
首先,先要明确几点:
1.指针也是一个变量,只不过这个变量中存的值是一个地址,理解这条是不被指针弄乱的关键。
2.非主函数的其他调用函数传递的形参只在其函数范围内起作用。
3.指针传递其实就是开了指向要改变的值的形参,由(3)知该指针作为调用函数形参仅在调用函数中有效,故指针传递的作用就是通过形参去改变固定地址中的值。
4.引用传递就相当于直接传递时直接在要传递值的地址上进行操作,省去了形参的使用,能提高效率。
以下分为两个部分讲:(都有多个例子)
1.指针传递
2.引用传递
一.指针传递
1.1:用指针改变单一值:
代码中含注解:
#include
#include
//test1:指针传递:对于指针传递,要改变传入的值的话,
//在调用函数中要用一个指针去指向要修改元素;
void change1(int a)//直接传入值,改变不了;
{
a=2;
}
void change2(int *w)//使用一个形参去改变地址对应的值;
{
*w=2;
}
int main()
{
int i,j;
int n,m;
int a=1;
printf("a的原值为:%d\n",a);
change1(a);//这个函数直接将变量值传入,不能改变;
//(相当于拷贝了一个同类型的变量在调用函数中改变,但改变的是拷贝过去的仅在调用函数中存在的形参);
printf("第一种改变方式:a==%d\n",a);
change2(&a);
//取出a的地址,在用一个指针形参去改变存储在该地址里的值;
printf("第二种改变方式后:a==%d\n",a);
}
1.2:改变指针变量的值:
为指针变量分配了一个随机地址。
指针也是一个变量,只不过这个变量中存的值是一个地址,理解这条是不被指针弄乱的关键。
#include
#include
#include
using namespace std;
//test2:改变指针变量的值,其实指针变量也是一个变量,
//指针变量也有自己的地址,所以用一个指向指针的指针去改变其地址里的值;
void change(int** a)//定义一个指向指针的指针形参;
{
*a=(int *)malloc(sizeof(int *));
//这里*a的含义是指向指针的指针的值(很拗口...但其实就是我们传进来那个指针变量);
}
int main()
{
int i,j;
int n,m;
int* a;//定义一个指针变量;
change(&a);//取出指针变量的地址(记得:指针也是一个变量,也有自己的地址)
printf("a==%d\n",a);
return 0;
}
1.3:改变数组的值
注意:数组的名字即对应了它的首地址故主函数中不用再次取其地址。
#include
#include
#include
using namespace std;
//test3:数组的指针传递;
//数组的名字就代表了它的首地址,故传入时不需要取地址;
void change(int* a)
{
a[0]=1;
a[1]=2;
a[2]=3;
a[3]=4;
a[4]=5;
}
int main()
{
int i,j;
int a[5]={0,1,2,3,4};
printf("原数组为:\n");
for(i=0;i<5;i++)
{
printf("%d ",a[i]);
}
printf("\n");
change(a);//名字即为其地址,不用再取地址;
printf("改变后:\n");
for(i=0;i<5;i++)
{
printf("%d ",a[i]);
}
printf("\n");
return 0;
}
小结:指针传递其实就是开多一个指针形参去指向要改变值的地址(只不过是不同时候要改变对象的类型不同),进而在调用函数中改变固定地址中的值。
二.引用传递
2.1改变单一值:
#include
#include
#include
using namespace std;
//test4:改变单一数;引用传递:引用传递的好处的它去直接改变地址中的值,
//不需要形参,提高了效率;
void change(int &a)
{
a=2;
}
int main()
{
int i,j;
int a=1;
printf("a==%d\n",a);
change(a);//直接将a传过去,不用取地址操作;
printf("改变后,a==%d\n",a);
}
2.2改变指针变量:
为指针随机分配了一个地址(记得:指针变量的值即是地址)
#include
#include
#include
using namespace std;
//test5:采用引用传递的方式改变指针;
void change(int* &a)//引用传递变量名前面的类型应与传入的变量一致;
{
a=(int *)malloc(sizeof(int *));
}
int main()
{
int i,j;
int n,m;
int* a;//定义一个int指针类型变量;
change(a);
printf("a==%d\n",a);
return 0;
}
2.3改变数组的值:
#include
#include
#include
using namespace std;
//test6:引用传递的方式改变数组;
void change(int (&a)[3])//数组的传递方式除了&数组名之外还要指出其长度
{ //(其实就是一系列连续指针变量空间)
a[0]=1;
a[1]=2;
a[2]=3;
}
int main()
{
int i,j;
int a[3]={0,1,2};
printf("改变前:\n");
printf("%d %d %d\n",a[0],a[1],a[2]);
change(a);//直接传数组名;
printf("改变后:\n");
printf("%d %d %d\n",a[0],a[1],a[2]);
return 0;
}
2.4:引用传递动态开辟空间:
用完free掉空间,这里就省掉了这个步骤。
#include
#include
//test7:引用传递动态开辟空间;
//以开长度为3的空间为例;
#define len 3
void change(int* &a)
{
a=(int*)malloc(len*sizeof(int *));//动态开len长度空间;
a[0]=1;
a[1]=2;
a[2]=3;
}
int main()
{
int* a;
int i,j;
change(a);
printf("%d %d %d\n",a[0],a[1],a[2]);
return 0;
}
结果:
小结:引用传递其实就相当于直接把那个实参本身传过去,改的就是那个实参对应的值,省去了开形参的步骤,也能提高效率,而且还不会被指针弄晕。