C语言中指针作为函数参数传递的问题

毕业论文是基于CUDA在GPU上做一些遥感影像处理的并行程序,开始大量使用CUDA C(大部分情况下就是标准C)。虽说是C号称是很“基础”的东西,大家上大学第一学年就学习过(甚至很多非计算机相关专业也要学),期末还能拿个90+,可最近频繁的掉坑还是再一次说明:编程这件事仅靠背书是断然不行的。下面总结一下刚刚踩过的一个C语言中较为有代表性的坑。
今天编程时遇到了一个问题,写到一个函数时,让这个函数通过参数返回内存某一个缓冲区的首地址。在网上找了找,发现以下这段代码比较有代表性,于是复制过来作为一个总结说明。

下面这段代码是典型的踩坑,这段代码通过函数申请一片内存区,并将申请到的内存首地址返回给调用函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
void getptr(int *p,int num) {
p = (int *)maccol(num * sizeof(int));
}
void main() {
int *ptr = NULL;
int k;
getptr(ptr,10);
if (ptr == NULL)
printf("Ptr is still NULL");
}

运行上边的代码,结果输出Ptr is still NULL,说明ptr指针根本没有像如我们设想的那样指向getptr()函数中分配的内存空间。

上边代码中,getptr(ptr,10)这一句传一个地址给getptr()里面的p指针,这时候p指针获得的是ptr指针的一个副本,确切的说是ptr指向的对象的内存地址,所以这种方式在函数里面可以用来传一个指针指向的数据,这个数据是引用,但是指针还是副本,就是pptr两个所指的数据是一样的,但是两个在内存的地址是不一样的。而我们的真正需求是用ptr指向获取一块动态分配的内存,所以当在函数中分配好内存空间,并将这块内存的首地址赋给p,这时候p指向的东西改变了,但没有影响到ptr指针。ptr指针的内容并未受到影响,只是p指针的数据改变了。所以这种情况下一个常见的解决方案就是,引入一个指针的指针,让p指针指向ptr这个指针(而不是ptr的副本),这时候动态的分配的数据块传给*p,这个*p就是ptr,所以给ptr分配内存成功。代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
void getptr(int **p,int num) {
*p = (int *)malloc(num * sizeof(int));
}
void main() {
int *ptr = NULL;
int k;
getptr(&ptr,10);
if (ptr == NULL)
printf("Ptr is still NULL");
}

参考资料:

  1. 阿来博客&追求卓越—-指针作为函数参数传递