目录
理解指针必须和内存四区的概念相结合才能透彻
1.主调函数 被调函数
a)主调函数可把堆区、栈区、全局数据内存地址传给被调用函数
b)被调用函数只能返回堆区、全局数据
2.内存分配方式
a)指针做函数参数,是有输入和输出特性的。如果是在主调用函数里面分配内存,把内存传给被调用函数,这种用法,叫指针的输入;如果是在被调用函数中分配的内存,同时把结果传到已分配的内存里面,然后,再输出让主调用函数使用,这种叫作指针的输出。
指针的输入输出特性案例(1级指针作输出)
在被调用函数中分配内存,理解指针的关键在于看内存是如何分配的。以下程序为例,通过看出在被调用函数中分配内存,可以看出这下面的示例是作输出的,同时看成这个被调用接口的2级指针是作输出的。也就是在被调用函数里面,须修改实参1级指针的值。看到2级指针的时候,要兵分两路,一路看2级指针在被调用函数的部分,一路看2级指针在主函数的部分(在主函数中要把1级指针的值的地址传入才行)。
int getMem41(char **myp1/*out*/ , int *mylen1 /*out*/, char **myp2 /*out*/, int *mylen2 /*out*/)
{
int ret = 0;
char *tmp1, *tmp2;
tmp1 = (char *)malloc(100);
strcpy(tmp1, "1132233");
//间接赋值
*mylen1 = strlen(tmp1); //1级指针
*myp1 = tmp1; //2级指针的间接赋值
tmp2 = (char *)malloc(200);
strcpy(tmp2, "aaaaavbdddddddd");
*mylen2 = strlen(tmp2); //1级指针
*myp2 = tmp2; //2级指针的间接赋值
return ret;
}
int main44()
{
int ret = 0;
char *p1 = NULL;
int len1 = 0;
char *p2 = NULL;
int len2 = 0;
ret = getMem41(&p1, &len1, &p2, &len2);
if (ret != 0)
{
printf("func getMem41() 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;
}
printf("p1:%d \n", p1);
system("pause");
return ret;
}
除了指针作函数参数,当我们想在被调用函数里面,把内存空间首地址扔出来,还有一种比较简单的方法:
注:返回值只能返回一个结果,不能返回俩
char * getMem42(int num)
{
int ret = 0;
char *tmp1;
tmp1 = (char *)malloc(num);
strcpy(tmp1, "1132233");
return tmp1;
}
int main44()
{
int ret = 0;
char *p1 = NULL;
int len1 = 0;
char *p2 = NULL;
int len2 = 0;
p1 = getMem42(100);
printf("p1:%s \n", p1);
if (p1 != NULL)
{
free(p1);
p1 = NULL;
}
printf("p1:%d \n", p1);
system("pause");
return ret;
}
应用指针必须和函数调用相结合(指针作函数参数)
编号 |
指针函数参数 内存分配方式(级别+堆栈) |
主调函数 实参 |
被调函数 形参 |
备注
|
||||
01 |
1级指针 (做输入) |
堆 |
分配 |
使用 |
一般应用禁用 |
|||
栈 |
分配 |
使用 |
常用 |
|||||
Int showbuf(char *p); int showArray(int *array, int iNum) |
||||||||
02 |
1级指针 (做输出) |
栈 |
使用 |
结果传出 |
常用 |
|||
int geLen(char *pFileName, int *pfileLen); |
||||||||
03 |
2级指针 (做输入) |
堆 |
分配 |
使用 |
一般应用禁用 |
|||
栈 |
分配 |
使用 |
常用 |
|||||
int main(int arc ,char *arg[]); 指针数组 int shouMatrix(int [3][4], int iLine);二维字符串数组 |
||||||||
04 |
2级指针 (做输出) |
堆 |
使用 |
分配 |
常用,但不建议用,转化成02 |
|||
int getData(char **data, int *dataLen); Int getData_Free(void *data); Int getData_Free(void **data); //避免野指针 |
||||||||
05 |
3级指针 (做输出) |
堆 |
使用 |
分配 |
不常用 |
|||
int getFileAllLine(char ***content, int *pLine); int getFileAllLine_Free(char ***content, int *pLine); |
总体代码
dm04_指针的输入和输出特性.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//
int getMem41(char **myp1/*out*/ , int *mylen1 /*out*/, char **myp2 /*out*/, int *mylen2 /*out*/)
{
int ret = 0;
char *tmp1, *tmp2;
tmp1 = (char *)malloc(100);
strcpy(tmp1, "1132233");
//间接赋值
*mylen1 = strlen(tmp1); //1级指针
*myp1 = tmp1; //2级指针的间接赋值
tmp2 = (char *)malloc(200);
strcpy(tmp2, "aaaaavbdddddddd");
*mylen2 = strlen(tmp2); //1级指针
*myp2 = tmp2; //2级指针的间接赋值
return ret;
}
char * getMem42(int num)
{
int ret = 0;
char *tmp1;
tmp1 = (char *)malloc(num);
strcpy(tmp1, "1132233");
return tmp1;
}
int main44()
{
int ret = 0;
char *p1 = NULL;
int len1 = 0;
char *p2 = NULL;
int len2 = 0;
ret = getMem41(&p1, &len1, &p2, &len2);
if (ret != 0)
{
printf("func getMem41() 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;
}
p1 = getMem42(100);
printf("p1:%s \n", p1);
if (p1 != NULL)
{
free(p1);
p1 = NULL;
}
printf("p1:%d \n", p1);
system("pause");
return ret;
}