您的位置:首页 > 其它

Day7(上).二级指针实战

2015-06-21 15:25 211 查看
首先练习一下二级指针做函数参数的问题,题目在代码最前面。

/*******************************************************************************************************************
题目:合并并排序两个指针数组,假如char *array1[] = { "bbbbb", "aaaaa", "ccccc", "22222", "11111", "44444" },
char array2[10][30] = { "zzzz", "yyyy", "xxxx" },合并输出{ "bbbbb", "aaaaa", "ccccc", "22222", "11111",
"44444", "zzzz", "yyyy", "xxxx" },并按照从小到大/从大到小的顺序输出结果。
思路:	1.定义一个二级指针,用于保存结果
2.在排序函数体内,将题目中的两个指针数组合并,然后排序
3.输出结果,释放内存空间
函数:	char **sortArray1Array2(char **pArray1, int nArray1Num, char(*pArray2)[30], int nArray2Num, int *nArray3Num)
void free_arr(char ** arr, int length)
说明:	二级指针做函数参数;二级指针做函数参数把结果甩出来;怎么malloc怎么free
*******************************************************************************************************************/
#define _CRT_SECURE_NO_WARNINGS
#include "stdlib.h"
#include "stdio.h"
#include "string.h"

//合并排序函数
char **sortArray1Array2(char **pArray1, int nArray1Num, char(*pArray2)[30], int nArray2Num, int *nArray3Num)
{
int i, j;
//输出结果的长度
int length = nArray1Num + nArray2Num;
//malloc输出结果的内存空间
char **pTmp = (char **)malloc((nArray1Num + nArray2Num)*sizeof(char *));
//一级指针分配内存
for (i = 0; i < length; i++)
{
pTmp[i] = (char *)malloc(sizeof(char) * 30);
memset(pTmp[i], 0, sizeof(char) * 30);
}
//把第一个指针数组复制到输出指针数组
for (i = 0; i < nArray1Num; i++)
{
strcpy(pTmp[i], pArray1[i]);
}
//把第二个指针数组复制到输出指针数组
for (int k = 0; k < nArray2Num; k++, i++)
{
strcpy(pTmp[i], pArray2[k]);
}
//排序
for (i = 0; i < length; i++)
{
for (j = 0; j < length; j++)
{
if (strcmp(pTmp[i], pTmp[j]) > 0)
{
char tmp[30] = { 0 };
strcpy(tmp, pTmp[i]);
strcpy(pTmp[i], pTmp[j]);
strcpy(pTmp[j], tmp);
}
}
}
//把输出指针数组的长度甩出来
*nArray3Num = length;
//返回输出结果指针数组
return pTmp;
}
void free_arr(char ** arr, int length)
{
int i;
//判断形参是否为空
if (arr == NULL)
{
return;
}
//释放内存空间,记住一点,怎么malloc怎么free
for (i = 0; i < length; i++)
{
if (arr[i] != NULL)
free(arr[i]);
}
//判断每一个一级指针是否为空,不为空释放
if (arr[i] != NULL)
{
free(arr);
}
}
void main()
{
int i;
//输出指针数组,指针切记要初始化
char **pArray3 = NULL;
int nArray3Num = 0;
//要合并的两个指针数组
char *array1[] = { "bbbbb", "aaaaa", "ccccc", "22222", "11111", "44444" };
char array2[10][30] = { "zzzz", "yyyy", "xxxx" };
//合并排序
pArray3 = sortArray1Array2(array1, 6, array2, 3, &nArray3Num);
//判断合并排序是否成功
if (pArray3 == NULL)
{
printf("func sortArray1Array2() err\n");
}
//打印输出指针数组
for (i = 0; i < nArray3Num; i++)
{
printf("%s \n", pArray3[i]);
}
//释放内存空间
if (pArray3 != NULL)
{
free_arr(pArray3, nArray3Num);
pArray3 = NULL;
}

system("pause");
}


在操作内存空间的时候,时刻要注意内存的分配和释放问题,必须要记住下面的初始化模版,做任何相关内存操作的项目,都必须首先在脑海中建立一个这样的初始化模型

/*******************************************************************************************************************
题目:合并并排序两个指针数组,假如char *array1[] = { "bbbbb", "aaaaa", "ccccc", "22222", "11111", "44444" },
char array2[10][30] = { "zzzz", "yyyy", "xxxx" },合并输出{ "bbbbb", "aaaaa", "ccccc", "22222", "11111",
"44444", "zzzz", "yyyy", "xxxx" },并按照从小到大/从大到小的顺序输出结果。
思路:	1.定义一个二级指针,用于保存结果
2.在排序函数体内,将题目中的两个指针数组合并,然后排序
3.输出结果,释放内存空间
函数:	char **sortArray1Array2(char **pArray1, int nArray1Num, char(*pArray2)[30], int nArray2Num, int *nArray3Num)
void free_arr(char ** arr, int length)
说明:	二级指针做函数参数;二级指针做函数参数把结果甩出来;怎么malloc怎么free
*******************************************************************************************************************/
#define _CRT_SECURE_NO_WARNINGS
#include "stdlib.h"
#include "stdio.h"
#include "string.h"

//合并排序函数
char **sortArray1Array2(char **pArray1, int nArray1Num, char(*pArray2)[30], int nArray2Num, int *nArray3Num)
{
int i, j;
int length;
//malloc输出结果的内存空间
char **pTmp = (char **)malloc((nArray1Num + nArray2Num)*sizeof(char *));
//一级指针分配内存
for (i = 0; i < length; i++)
{
pTmp[i] = (char *)malloc(sizeof(char) * 30);
memset(pTmp[i], 0, sizeof(char) * 30);
}

/******************************************/

//返回输出结果指针数组
return pTmp;
}
void free_arr(char ** arr, int length)
{
int i;
//判断形参是否为空
if (arr == NULL)
{
return;
}
//释放内存空间,记住一点,怎么malloc怎么free
for (i = 0; i < length; i++)
{
if (arr[i] != NULL)
free(arr[i]);
}
//判断每一个一级指针是否为空,不为空释放
if (arr[i] != NULL)
{
free(arr);
}
}
void main()
{
int i;
//输出指针数组,指针切记要初始化
char **pArray3 = NULL;
int nArray3Num = 0;
//要合并的两个指针数组
char *array1[] = { "bbbbb", "aaaaa", "ccccc", "22222", "11111", "44444" };
char array2[10][30] = { "zzzz", "yyyy", "xxxx" };
//合并排序
pArray3 = sortArray1Array2(array1, 6, array2, 3, &nArray3Num);
//判断合并排序是否成功
if (pArray3 == NULL)
{
printf("func sortArray1Array2() err\n");
}

/******************************************/

//释放内存空间
if (pArray3 != NULL)
{
free_arr(pArray3, nArray3Num);
pArray3 = NULL;
}

system("pause");
}



———————————————————————————————————————————————————————————————————————————

下面是本节重点,有关二级指针做输出的问题。在学习完下面的内容之后,必须深刻理解这句话:

二级指针做函数参数(形参),在被调用函数里面修改实参。

如下是一个简单的例子,说明如何用一级指针去修改0级指针的值

#define _CRT_SECURE_NO_WARNINGS
#include "stdlib.h"
#include "stdio.h"
#include "string.h"

//用一级指针(通常是形参),去修改0级指针(通常是实参)的值
int  getlen(int *p)
{
*p = 20;
}
void main()
{
    int a;
    int *p = NULL;

    p = &a;
    //直接修改a的值
    a = 1;
    //p是a的地址,*(a的地址)去间接修改a的值
    *p = 10;
    //1级指针去修改0级指针的值
    getlen(&a);
    printf("a:%d \n", a);

    system("pause");
}
我们再深入一层,用二级指针去修改一级指针的值

#define _CRT_SECURE_NO_WARNINGS
#include "stdlib.h"
#include "stdio.h"
#include "string.h"

//用二级指针去修改一级指针的值
void main()
{
char *p = NULL;
char ** p2 = NULL;
//直接修改p的值
p = 0x11;
printf("p:%x \n", p);

//此处要理解&p的意义,即p成了和p2一样的“二级指针”
p2 = &p;
//*(p2)即为*(&p)=p,为了理解而这样解释
*(p2) = 0x22;
printf("p:%x \n", p);

system("pause");
}
我们用函数体的形式实现上面的代码,在上面的形式上继续修改

#define _CRT_SECURE_NO_WARNINGS
#include "stdlib.h"
#include "stdio.h"
#include "string.h"

//用二级指针(通常是形参),去修改一级指针(通常是实参)的值
int getmembuf(char **p2)
{
//*(p2)即为*(&p)=p,为了理解而这样解释
*(p2) = 0x33;
return 0;
}
void main()
{
char *p = NULL;
char ** p2 = NULL;
//直接修改p的值
p = 0x11;
printf("p:%x \n", p);

//此处要理解&p的意义,即p成了和p2一样的“二级指针”
p2 = &p;
//*(p2)即为*(&p)=p,为了理解而这样解释
*(p2) = 0x22;
printf("p:%x \n", p);

getmembuf(&p);
printf("p:%x \n", p);

system("pause");
}
但是这样做的意义何在呢???为什么要这样用二级指针???

下面看继续修改的结果代码,只修改int getmembuf函数体

//用二级指针(通常是形参),去修改一级指针(通常是实参)的值
//相当于在被调用函数体内分配内存,把结果给甩出来
int getmembuf(char **p2)
{
    //1.便于理解
    //函数体内分配内存空间,使用二级指针将其甩出来
    char **tmp;
    tmp = (char *)malloc(100);
    p2 = tmp;
    //2.实际项目这样写
    p2 = (char *)malloc(100);
    
    return 0;
}
必须掌握上面的用法,二级指针做函数参数,函数体内分配内存,用二级指针把结果甩出来!!!!否则,C/C++的指针是白学的!!!!
总之,二级指针做函数参数(形参),在被调用函数里面修改实参。

———————————————————————————————————————————————————————————————————————————

二级指针做输出易犯错误

1.首先看第一个例子

#include "stdlib.h"
#include "stdio.h"
#include "string.h"

int getmembuf(char **p)
{
char **tmp;
tmp = (char *)malloc(100);
*p = tmp;
return 0;
}
void main()
{
char **p = NULL;
getmembuf(p);
system("pause");
}
上面的例子,一执行就会down掉,为什么呢???我们来分析一下它的内存模型



2.show the codes

#include "stdlib.h"
#include "stdio.h"
#include "string.h"

int getmembuf1(char **p)
{
char **tmp;
tmp = (char *)malloc(100);
tmp = "aaaaaaannnnnnnn";
*p = tmp;
return 0;
}

void main()
{
//buf指针是一个const类型,无法修改
char buf[10];
//此处buf当作形参是错误的
getmembuf1(&buf);
printf("%s", buf);

if (buf != NULL)
{
free(buf);
}
system("pause");
}
需要特别注意,二级指针做函数参数的时候,必须能够修改,即必须非const类型,上面代码的char buf[10]是无法修改内存地址的,切记!!!

3.重复提及的二级指针做函数参数,在被调用函数里分配内存,并把结果甩出函数体。

看下面的代码对比

void getmembuf(char *buf)
{
char * tmp;
tmp = (char)malloc(100);
buf = tmp;
return;
}

void getmembuf(char **buf)
{
char ** tmp;
tmp = (char*)malloc(100);
buf = tmp;
return;
}


不多说了,不解释,自己看!!!二级指针做函数参数,在被调用函数里分配内存的精髓就是这两段代码!!!

4.结构体中的问题

看第一段代码

#include "stdlib.h"
#include "stdio.h"
#include "string.h"

struct Teacher
{
char name[10];
int age;
};

struct Teacher *createTeacher()
{
struct Teacher *tmp = NULL;
tmp = (struct Teacher *)malloc(sizeof(struct Teacher));
return tmp;
}
void main()
{
struct Teacher *t1 = createTeacher();

if (t1 != NULL)
{
free(t1);
}
system("pause");
}
看第二段代码

#include "stdlib.h"
#include "stdio.h"
#include "string.h"

struct Teacher
{
char name[10];
int age;
};

int createTeacher(struct Teacher **p)
{
    //不要相信别人给你传的地址是可用的
    if (p == NULL)
        return -1;
    struct Teacher *tmp = NULL;
    tmp = (struct Teacher *)malloc(sizeof(struct Teacher));
    *p = tmp;
    return 0;
}

void main()
{
struct Teacher *t = NULL;
createTeacher(&t);

if (t != NULL)
{
free(t);
}

system("pause");
}

仔细观察如何将struct Teacher *createTeacher()替换成int createTeacher(struct Teacher **p)!!!

还不懂????继续延伸!!!!

#include "stdlib.h"
#include "stdio.h"
#include "string.h"

int getmembuf(char ****p)
{
*p = 0x4;
}
void main()
{
char ****p1 = NULL;
char *****p2 = NULL;
//直接修改
p1 = 0x1;
p1 = 0x2;

//间接修改
p2 = &p1;
*p2 = 0x3;
printf("%d\n", p1);
//间接修改2
getmembuf(&p1);
printf("%d\n", p1);

system("pause");
}

一定要明白N级指针修改N-1级指针内存空间的方法!!!!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: