指针与函数参数传递
C语言在传递参数时,会默认为形参分配新的内存空间,形参只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。
void main()
{
int i = 10;
change(i);
printf(“i = %d”,i) //此处输出i = 10;
printf("main方法i 的地址:%x",&i) //打印i的地址
}
void change(int i)
{
i = 20;
printf("change方法i 的地址:%x",&i) //打印i的地址
}
我们可以看到,调用change()方法后并没有改变i的值,我们可以把main方法和change()方法中的变量地 址打印出来看是否相同。我们可以看到两个地址的值是不一样的。故我们认为他们不是同一个变量,这是因为编 译器为形参分配了新的内存空间存储,当方法执行完之后,该内存空间被释放。在方法中改变形参并不会对实参 造成影响。我们称这种传递为值传递。
那么,我们如何才能在chang方法中改变i的值呢?指针这时候就派上用场了。
void main(){
int i = 10;
int *p = &i;
change(p); //传递的是i的地址
printf(“i = %d”,i) //此处输出i = 20;
}
void change(int *p)
{
*p = 20;
}
我们把参数的地址传入方法,实现了通过指针改变量的值。由此我们知道要想在外部方法中改变一个变量需要变量的地址。不是所有参数传递都是值传递,数组作为参数传递时就是地址传递。
数组与指针
int a[5] = {1,2,3,4,5}; //定义一个数组
printf(“%x %x”,a,&a);
C语言中数组名是一个常量,不可赋值。数组名即是数组的名称,同时又是数组的首地址。我们可以看到打印出 的a和&a值是一样的。
int * p =a;//声明一个指针变量,指向数组首元素地址。
printf(“%d %d”,*p,a[0]); //打印*p的值和a[0]的值
我们可以看到此处*p = a[0],p = &a[0];
我们知道a+1是指针前进一个sizeof(int),故此,我们可以通过指针循环遍历数组:
for (int i = 0; i < 5; i++)
{
printf("a[%d] = %d", i, *(a + i)); //通过地址访问
printf("a[%d] = %d", i, a[i]); //通过数组下标访问
}
可以看到,打印出来的值是一致的。
我们得出结论:
a[i] = *(a+i);
数组作为参数传递时,传递的是数组的首地址,这种传递称之为地址传递
void arraytest(int a[5])
{
printf("数组地址: %x \n",a);
}
void main()
{
int a[5] = { 1, 2, 3, 4, 5 };
printf("数组地址:%x \n",a);
arraytest(a);
}
上面代码结果可以看出,实参和形参的数组首地址是相同的。
二级指针
指针变量作为一个变量,占据内存空间,有其地址,故可以用一个指针指向它,指向指针的指针我们称之为二级指针,该二级指针保存了一级指针变量的地址。我们假设有两个箱子,b箱子放着宝贝,但b箱子的钥匙锁在a箱子里这里,a箱子可以看成是二级指针。
二级指针的声明
int num =100;
int *p = &num
int **pp = &p;
printf("i = %d,i = %d", *p,**pp); //打印*p和**pp的值
我们可以看到*p和**pp的值是相同的。
**pp = *p = num
*pp = p =&num
pp = &p
什么时候用到二级指针呢?我们知道要在外部方法中改变一个变量的值需要传变量的地址,那么我们要改变一个指针的值就需要传递指针的指针即二级指针。
void change(int **p,int *num)
{
*p = num ; // *p为变量num1的地址,改变指针的指向,使指针由原来指向num1变成指向num2 ;
printf("地址2:%x \n",p);
printf("变量:%d \n", **p);
}
void main()
{
int num1 = 100;
int num2 = 200;
int *p = &num1;
int **pp = &p;
printf("修改前的地址1:%x \n", p);
change(pp, &num2);
printf("修改后的地址3:%x \n", p);
printf("修改后指针指向的值 num = %d \n", *p);
}
我们可以看到修改前和修改后指针p的值是不同的。二级指针作为参数传递可以改变一级指针的值。
待续......