首先看看一个看着没有什么问题的代码(先不考虑内存泄漏这个问题蛤):这个程序看起来人畜无害,指针ptr将指向mymolloc()的malloc()函数分配的地址,因为main()函数传入的就是指针ptr的值,它表示的不就是一个地址,但是看看输出的结果,看看对不对。
#include <stdio.h>
#include <stdlib.h>
int mymolloc(int *ptr)
{
printf("%s: the ptr address is 0x%lx\n", __func__, (unsigned long)ptr);
ptr = malloc(sizeof(100));
printf("%s: the ptr address is 0x%lx\n", __func__, (unsigned long)ptr);
return 0;
}
int main(int argc, char **argv[])
{
int *ptr = NULL;
printf("%s: the ptr address is 0x%lx\n", __func__, (unsigned long)ptr);
mymolloc(ptr);
printf("%s: the ptr address is 0x%lx\n", __func__, (unsigned long)ptr);
}
main: the ptr address is 0x0
mymolloc: the ptr address is 0x0
mymolloc: the ptr address is 0x5638179786b0
main: the ptr address is 0x0
呀,不对呀,为什么ptr还是0x0,em…,挺令人费解的,这里我们可以这样理解,我们都知道要想修改主函数某个变量的值,如果仅仅是传入一个实参,在被调函数中这个值确实会发生改变,但是由于局部变量作用域的缘故,当程序调用结束时,栈会被释放掉,那么主函数中变量的值并没有变化(如果有返回另当别论),那么这个时候我们就引入了指针,通过修改指针指向的数据从而修改变量的值,这个也可以类比到这个例子。
我们这里的目的是修改指针变量ptr的值,那我们是不是应该解引用两次,而传入参数应该取地址(&)~~
#include <stdio.h>
int change_a(int a)
{
a = 100;
return a;
}
void change_two(int a)
{
a = 100;
}
void change_three(int *p)
{
*p = 100;
}
int main(void)
{
int a = 10, result = 0;
result = change_a(a);
printf("%s: result = %d\n", __func__, result);
change_two(a);
printf("%s: a = %d\n", __func__, a);
change_three(&a);
printf("%s: a = %d\n", __func__, a);
return 0;
}
main: result = 100
main: a = 10
main: a = 100
#include <stdio.h>
#include <stdlib.h>
int mymolloc(int **ptr)
{
printf("%s: the ptr address is 0x%lx\n", __func__, (unsigned long)ptr);
*ptr = malloc(sizeof(100));
printf("%s: the ptr address is 0x%lx\n", __func__, (unsigned long)ptr);
return 0;
}
int main(int argc, char **argv[])
{
int *ptr = 0;
printf("%s: the ptr address is 0x%lx\n", __func__, (unsigned long)ptr);
mymolloc(&ptr);
printf("%s: the ptr address is 0x%lx\n", __func__, (unsigned long)ptr);
}
main: the ptr address is 0x0
mymolloc: the ptr address is 0x7ffd1a305410
mymolloc: the ptr address is 0x7ffd1a305410
main: the ptr address is 0x55dffe4176b0
或者我们可以这样改:
#include <stdio.h>
#include <stdlib.h>
int mymalloc(unsigned long ptr2)
{
(*(unsigned long *)ptr2) = (unsigned long)malloc(128);
return 0;
}
int main(int argc, char **argv)
{
int *ptr = 0;
mymalloc(&ptr);
printf("%lx", (unsigned long)ptr);
free(ptr);
*((unsigned long *)ptr) = 122;
return 0;
}
这样虽然编译时有警告,但是结果还是没有问题的。