目录
三种内存模型的本质
如果内存模型建立不起来,不可能成为高手!
针对之前的对二级指针的三种内存模型的总结可以得出:第一种内存模型是一个一维数组;第二种内存模型是一个二维数组;第三种内存模型是手工二维内存模型。那么如何将这三种内存模型在内存四区的分布情况都画出来呢?
上面就是p1,p2,p3三种模型的对应的变量的内存模型示意图,需要让我自己记住的是,画内存四区的示意图时,先看等号右边的,看看分配的大小,再看等号左边的看看分配的数据类型是什么,比如到p2的时候,我以为应该和p1一样,也在全局区分配内存,结果却是在缓存区分配的,这是因为p2的数据类型是数组,p1的数据类型是指针,数据类型的不同觉得了分配的方式不同;还有,p2是个二维数组,但只管第一维是怎么分配的。
注意,第一种内存模型与第三种内存模型很相似,只是放的地方不一样。而且,“p1+1”和“p3+1”都是往后跳一个指针的长度,这也是为什么之前的相同的排序函数都可以适用于第一种和第三种内存模型的原因,就是因为这俩模型的步长是一样的,都是往后跳一个指针的长度(4个字节或八个字节)。
再看第二种内存模型就不一样了,它的步长就i和上面俩不一样了,“p2+1”往后跳,就得跳4*4个字节了,因为它第二维还包含着数组,所以,跳的步长是不一样的。
因为所有数组,无论是二维还是多维,都是我们程序员手工、人为规定的,而对于编译器存储,所有数据在内存中都是线性存储的,这也就是为啥说跳的步长不一样的原因了,这也是存在指针做函数参数退化的问题,至于怎么个不一样法,看下一博客。
下面是另一个版本的三种模型的内存示意图,引做对比参考:
多级指针的使用
如果一个包含多级指针的函数必须通过指针做函数参数的方式,把内存空间给传出来,就相当于要用一级指针形参去改变零级实参指针的值,用二级形参指针去改变一级指针实参的值,用三级形参指针去改变二级指针实参的值,。。。。,用n级形参指针去改变n-1级指针实参的值。
void getMem52_Free(char ***p3 , int num)
{
char **tmp = NULL;
if (p3 == NULL)
{
return ;
}
*p3 = tmp; //*p3指向主调函数中的p2,可直接改变p2的值。
}
void main()
{
char **p2 = NULL;
getMem52_Free(&p2, num);
printf("hello...\n");
system("pause");
return ;
}
如上,在主调函数中的一个二级指针,要想通过被调函数控制它,就需要引入这个二级指针变量的地址,即通过三级指针来调用它。而且,在被调函数中,判断是指针变量本身,而不是指针所指向的内容。
总体代码
dm05_二级指针内存模型.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void main2()
{
int i = 0;
//指针数组
char * p1[] = {"123", "456", "789"};
//二维数组
char p2[3][4] = {"123", "456", "789"};
//手工二维内存
char **p3 = (char **)malloc(3 * sizeof(char *)); //int array[3];
for (i=0; i<3; i++)
{
p3[i] = (char *)malloc(10*sizeof(char)); //char buf[10]
sprintf(p3[i], "%d%d%d", i, i, i);
}
}
void main555()
{
printf("hello...\n");
system("pause");
return ;
}
dm06_玩转多级指针.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
char **getMem51(int num)
{
int i = 0;
char **p2 = NULL;
p2 = (char **)malloc(sizeof(char *) * num);
if (p2 == NULL)
{
return NULL;
}
for (i=0; i<num; i++)
{
p2[i] = (char *)malloc(sizeof(char) * 100 ); //char buf[100];
sprintf(p2[i], "%d%d%d", i+1, i+1, i+1);
}
return p2;
}
int getMem52(char ***p3 , int num)
{
int i = 0;
char **tmp = NULL;
if (p3 == NULL)
{
return -1;
}
tmp = (char **)malloc(sizeof(char *) * num);
if (tmp == NULL)
{
return NULL;
}
for (i=0; i<num; i++)
{
tmp[i] = (char *)malloc(sizeof(char) * 100 ); //char buf[100];
sprintf(tmp[i], "%d%d%d", i+1, i+1, i+1);
}
*p3 = tmp;
//1 2
return 0;
}
void getMem52_Free(char ***p3 , int num)
{
int i = 0;
char **tmp = NULL;
if (p3 == NULL)
{
return ;
}
tmp = *p3;
for (i=0; i<num; i++)
{
free(tmp[i]);
}
free(tmp);
*p3 = NULL; //把实参赋值成null
}
void main66()
{
int i = 0, j = 0;
char **p2 = NULL;
int num = 5;
char *tmp = NULL;
char tmpbuf[100];
//p2 = getMem51(num);
getMem52(&p2, num);
for (i=0; i<num; i++)
{
printf("%s \n", p2[i]);
}
getMem52_Free(&p2, num);
printf("hello...\n");
system("pause");
return ;
}