经常会总结指针的用法和注意点,由于工作中基于学习到的深度学习网络模型构建功能时会遇到各种指针的使用,在实践中终于明白了指针的第一大重点是作为函数参数。接下来介绍下,一级指针,二级指针作为函数参数时实现的功能和注意事项。
所谓输出功能:将main函数中定义的指针的地址传入子函数,在子函数中分配内存空间(“堆” or “常量”,因为只有这两个地方的内存空间不会在子函数结束后被释放掉),并对内存空间赋值,最后将传入子函数形参的指针指向该内存空间,最终做到向形参指针输出一些内容,具体实例如下所示:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int getMem(char **myp1/*out*/ , int *mylen1 /*out*/, char **myp2 /*out*/, int *mylen2 /*out*/)
{
int ret = 0;
char *tmp1, *tmp2;
tmp1 = (char *)malloc(100);
strcpy(tmp1, "ylylylylyl");
//间接赋值
*mylen1 = strlen(tmp1); //1级指针
*myp1 = tmp1; //2级指针的间接赋值
tmp2 = (char *)malloc(200);
strcpy(tmp2, "lylylylyly");
*mylen2 = strlen(tmp2); //1级指针
*myp2 = tmp2; //2级指针的间接赋值
return ret;
}
int main()
{
int ret = 0;
char *p1 = NULL;
int len1 = 0;
char *p2 = NULL;
int len2 = 0;
ret = getMem(&p1, &len1, &p2, &len2);
if (ret != 0)
{
printf("func getMem() err:%d \n", ret);
return ret;
}
printf("p1:%s \n", p1);
printf("p2:%s \n", p2);
if (p1 != NULL)
{
free(p1);
p1 = NULL;
}
if (p2 != NULL)
{
free(p2);
p2 = NULL;
}
}
上述代码段,介绍了一级指针和二级指针,作输出功能的函数参数的情况。我们可以发现,对于一级和二级指针作输出功能的函数参数时,使用方式和需要注意的点是一致的。
1.在main函数中定义参数
int ret = 0;
char *p1 = NULL;
int len1 = 0;
char *p2 = NULL;
int len2 = 0;
上述代码段在main函数中定义变量,包括了指针变量和整型变量。相当于是在main函数内为这两类变量分配好了内存空间。
2.对参数取地址,传入子函数
int getMem(char **myp1/*out*/ , int *mylen1 /*out*/, char **myp2 /*out*/, int *mylen2 /*out*/)
ret = getMem(&p1, &len1, &p2, &len2);
上述代码段将定义在main函数中的参数取地址后送入子函数,由于指针取地址变成二级指针,整型变量取地址变成指针,因此子函数的形参定义如上述代码段第一行所示。这种情况下,一级和二级指针是作输出功能的,所谓输出就是说在子函数中会对这两类指针进行间接赋值,并通过指针的方式将这两类指针变量所指向的值带出子函数在其他函数中使用。
3.在子函数中,对形参的地址中的值进行修改(利用*变量名)
char *tmp1, *tmp2;
tmp1 = (char *)malloc(100);
strcpy(tmp1, "ylylylylyl");
//间接赋值
*mylen1 = strlen(tmp1); //1级指针
*myp1 = tmp1; //2级指针的间接赋值
---------------------------------------------------------
if (p1 != NULL)
{
free(p1);
p1 = NULL;
}
如上述代码所示,就是间接复制的具体实现方式。在子函数中利用malloc
在堆上分配内存,因为堆上的内存在子函数结束后不会自动析构掉,需要程序员手动释放。(若不释放会导致内存泄漏。)修改堆内存上的值,并将形参指向堆,从而实现间接赋值。