为什么要用指针,什么时候该用指针,什么时候该用指针的指针

为什么要用指针,什么时候该用指针,什么时候该用指针的指针

为什么要用指针,什么时候该用指针,什么时候该用指针的指针

序一、什么时候该用指针(1)动态数组(2)一些功能性声明(3)传参改变变量

二、什么时候该用指针的指针(1)通过传递二级指针改变量(2)无法靠传一级指针改变指针时(3)更新ing...

很多内容可以参考同专栏的其他文章,像指针&结构体、字符串,函数指针,数组指针,指针基础概念与内存分配等。

几个必须了解的前提概念: (1)指针是一个保存地址的变量。这个地址是指针所指向的变量的地址而不是指针本身的地址。 (2)C语言的参数传递方式有值传递和地址传递。 (3)C语言中参数传递的本质都是值传递。 (4)形参在调用返回时就会被销毁,它只是拷贝了一份实参,形参的改变对实参没有影响。 (*5)一个实参指针变量传入函数的形参指针变量时,指针指向的内容是可以改变的,但是指针的值和地址本身是不会改变的。 (*6)C语言的变量一但声明赋值后,就会分配一块内存,这块内存的地址是不会改变的。 (7)数组作为形参传递时,形参实参是同一块内存。

一、什么时候该用指针

(1)动态数组

指针做动态数组声明用:int *arr;:指针名就是数组名,直接解引*arr就是数组的首项值。

(2)一些功能性声明

函数指针或数组指针。

(3)传参改变变量

当要调用函数改变一个变量的值时,就要用到指针。因为形参不改变实参。 例如:

void swapValue(int num1,int num2)

{

int temp;

temp = num1;

num1 = num2;

num2 = temp;

printf("-------swapValue-------\n\r");

printf("num1=%d\n\r",num1);

printf("num2=%d\n\r",num2);

}

void swapPoint(int *p1,int *p2)

{

int temp;

temp = *p1; //tmp=a

*p1 = *p2; //a=b

*p2 = temp; //b=tmp

printf("-------swapPoint-------\n\r");

printf("*p1=%d\n\r",*p1);

printf("*p2=%d\n\r",*p2);

}

void swapPoint2(int *p1,int *p2)

{

int *temp;

temp = p1; //tmp=&a

p1 = p2; //&a=&b

p2 = temp; //&b=tmp

printf("-------swapPoint2-------\n\r");

printf("*p1=%d\n\r",*p1);

printf("*p2=%d\n\r",*p2);

}

int main()

{

int a = 5;

int b = 10;

printf("a=%d\n",a);

printf("b=%d\n",b);

printf("aAdd=%p\n",&a);

printf("bAdd=%p\n",&b);

swapValue(a,b);

printf("a=%d\n",a);

printf("b=%d\n",b);

printf("aAdd=%p\n",&a);

printf("bAdd=%p\n",&b);

swapPoint(&a,&b);

printf("a=%d\n",a);

printf("b=%d\n",b);

printf("aAdd=%p\n",&a);

printf("bAdd=%p\n",&b);

swapPoint2(&a,&b);

printf("a=%d\n",a);

printf("b=%d\n",b);

printf("aAdd=%p\n",&a);

printf("bAdd=%p\n",&b);

return 0;

}

可自己先演算一下结果再与下方结果对比。

编译结果: 逐个分析: swapValue:传递的是值,形参再怎么变化,函数返回时就会从栈中销毁,因此只会改变形参num1,2的值,不会改变a,b的值,地址就更不用说了。

swapPoint:传递的是指针,这下形参是指针,因此指针便不会改变,但是指针所指向的内容可以改变,因此a,b的值就发生了互换,但是地址不变化。

swapPoint2:传递的是指针,同swapPoint一样,但是内部是直接对形参的指针变量进行交换操作,即互换地址,因此解引形参时相当于将前面调换的值调换回来了。但是函数返回时一切销毁,所以a,b的值和地址都不会变化,而且C语言定义的变量地址是无法改变的。

二、什么时候该用指针的指针

(1)通过传递二级指针改变量

通过传入指向一块内存的地址值的指针(即指针的指针),间接修改指向的值。

例如:

void swap2Pointer(int** p1,int** p2)

{

int temp;

printf("-------into swapAddr-------\n\r");

printf("**p1=%d\n\r",**p1); //p1=&x,*p1=&a,**p1=a

printf("**p2=%d\n\r",**p2);

temp = **p1;

**p1 = **p2;

**p2 = temp;

printf("-------after swapAddr-------\n\r");

printf("**p1=%d\n\r",**p1);

printf("**p2=%d\n\r",**p2);

}

int main()

{

int a = 5;

int b = 10;

printf("a=%d\n",a);

printf("b=%d\n",b);

printf("aAdd=%p\n",&a);

printf("bAdd=%p\n",&b);

int *x = &a;

int *y = &b;

swap2Pointer(&x,&y);

printf("a=%d\n",a);

printf("b=%d\n",b);

printf("aAdd=%p\n",&a);

printf("bAdd=%p\n",&b);

}

编译结果: 拓展:上面说过传入形参的实参是不会改变的(因为函数返回时就销毁),但是指向的内存是可以改变的(现在指向的是a的地址的值),那么将上述swap2Pointer修改为如下swapAddr是不是就能改变*p1(&a)和*p2(&b)了,从而调换x和y指向的地址值,答案是可以的。 如下:

void swapAddr(int** p1,int** p2)

{

int temp;

printf("-------into swapAddr-------\n\r");

printf("*p1=%x\n\r",*p1); //p1=&x,*p1=&a,**p1=a

printf("*p2=%x\n\r",*p2);

temp = *p1;

*p1 = *p2;

*p2 = temp;

printf("-------after swapAddr-------\n\r");

printf("*p1=%x\n\r",*p1);

printf("*p2=%x\n\r",*p2);

}

int main()

{

int a = 5;

int b = 10;

printf("a=%d\n",a);

printf("b=%d\n",b);

printf("aAdd=%p\n",&a);

printf("bAdd=%p\n",&b);

int *x = &a;

int *y = &b;

printf("*x=%d\n",*x);

printf("*y=%d\n",*y);

swapAddr(&x,&y);

printf("a=%d\n",a);

printf("b=%d\n",b);

printf("aAdd=%p\n",&a);

printf("bAdd=%p\n",&b);

printf("*x=%d\n",*x);

printf("*y=%d\n",*y);

}

编译如下:

(2)无法靠传一级指针改变指针时

像如下代码编译时会奔溃,因为num传入p时,num是无法被改变的,因此num没有开辟出空间无法赋值。

void pMalloc(int *p,int size)

{

p = (int *)malloc(size*sizeof(int));

}

int main()

{

int *num = NULL; //如果是全局和static会自动初始化为NULL

pMalloc(num,5);

if(num!=NULL)

{

*num = 200;

printf("num=%d",*num);

}

else

{

printf("Assignment Fail");

}

return 0;

}

编译结果:

而如果将传入的参数变成实参变量的地址的话:

void pMalloc(int **p,int size)

{

*p = (int *)malloc(size*sizeof(int));

}

int main()

{

int *num = NULL; //如果是全局和static会自动初始化为NULL

pMalloc(&num,5); //p=#*p=num;**p=*num

if(num!=NULL)

{

*num = 200;

printf("num=%d",*num);

}

else

{

printf("Assignment Fail");

}

return 0;

}

编译结果:(成功) 记住前面序中的几点概念,那么玩转指针就很简单了。而多级指针如果很乱的话,就像上面程序中p=#*p=num;**p=*num这样抽丝剥茧即可。

(3)更新ing…

若想通过函数修改变量值,可以通过传递指针以修改目标地址上存储的值,而变量的地址是不能改变的。不管是几级指针,最终改变的一定是对应地址上的内存,即以"值"形式存在的数据。

相关推荐

科学撸猫指南(完全版)
365提款会被冻结卡吗

科学撸猫指南(完全版)

📅 07-10 👁️ 7460
你家冰箱多久没消毒了?别让冰箱成为病菌的家,4招给冰箱消毒
偷袭的意思
365提款会被冻结卡吗

偷袭的意思

📅 08-16 👁️ 8265