首先看个比较简单的例子,我们需要实现一个a、b交换的函数
若使用值传递的方式则可能写成如下:
#include
#include
typedef unsigned char uint8_t;
void swop(uint8_t k, uint8_t n)
{
uint8_t temp;
temp = k;
k = n;
n = temp;
}
void main(void)
{
uint8_t a = 3,b = 5;
swop(a,b);
printf("a = %d,b = %d\r\n",a,b);
while(1);
}
测试会发现主函数调用swop函数后,a、b值根本不会发生改变:
原因:k、n是系统在发生函数调用时生成的临时变量,虽然值和a、b相同,但却是两个不同地址空间的变量,这两个临时变量是运行swop函数临时生成的和主程序中的变量是完全独立的。在函数中我们看到临时变量k、n的值确实改变了,但swop函数调用完成后当返回主程序时,a、b的值并没有改变。
修改程序如下:
#include
#include
typedef unsigned char uint8_t;
void swop(uint8_t *k, uint8_t *n)
{
uint8_t temp;
temp = *k;
*k = *n;
*n = temp;
}
void main(void)
{
uint8_t a = 3,b = 5;
swop(&a,&b);
printf("a = %d,b = %d\r\n",a,b);
while(1);
}
分析:修改程序后调用swop函数则传递的是a、b的地址值,swop函数内部交换操作则真正实现了对实际a、b地址指向的值交换。
接着我们看一个复杂点的例子,原理相同,却经常被忽视。功能是实现通过fun返回 test_buf的首地址功能。
经常回错误的写成如下:
#include
#include
typedef unsigned char uint8_t;
uint8_t test_buf[10] = {1,2,3,4,5,6,7,8,9,0};
/*通过fun返回 test_buf的首地址*/
void fun(uint8_t *p_back)
{
p_back = test_buf;
}
void main(void)
{
uint8_t *p = NULL;
fun(p);
printf("back data:%d\r\n",p[0]);
while(1);
}
分析:实际运行根本不能得到想要的结果,p也不会指向test_buf。原因一样,*p_back 是发生fun调用时生成的临时指针变量,p_back和主函数中的p是不同地址空间的指针变量,虽然与p值相同,但不会改变p的值
正确的写法如下:
#include
#include
typedef unsigned char uint8_t;
uint8_t test_buf[10] = {1,2,3,4,5,6,7,8,9,0};
/*通过fun返回 test_buf的首地址*/
void fun(uint8_t **p_back)
{
*p_back = test_buf;
}
void main(void)
{
uint8_t *p = NULL;
fun(&p);
printf("back data:%d\r\n",p[0]);
while(1);
}
分析如下:**p_back 表示指针的指针,也就是指针的地址,发生fun调用时是地址传递。变量都是有地址的,主函数中发生fun调用时传递的是&p,也就是指针p的地址,指针p的地址当然就是存放p指针变量的地址值,此时fun的功能就变成了将test_buf的首地址值赋值给p的地址,指针p变量地址的内容就变成了test_buf的首地址,则p指向了test_buf。
用更简单易理解的话说就是:你要传回去的是指针 所以需要一个指向指针的指针