C语言中的指针用的是比较多,一级指针和二级指针时最常见的。其中,在C语言中二级指针相对于一级指针要难一些,下面就介绍一下C语言中二级指针的三种内存模型。
一、二维数组char a[5][5]内存模型
#include<stdio.h> #include<malloc.h> #include<string.h> /* C语言中的二级指针的三种内存模型 */ //第一种模型,二维数组char a[5][5] void func1(){ //二维数组,表示有5个大小为5的字符串(实际上这个字符串的大小只能为4,因为最后一位用来存储'\0'表示结束) char a[5][5] = { "zxcv", "mnbv", "gbde", "abde", "1234"}; //如果字符的长度为5,如"abcde"就会导致,a[0]为"abcde1234",因为相当于你用字符'e'代替了'\0' //对二维数组a进行排序,由小到大 //交换它们的内容,利用冒泡排序 char temp[5] = {0}; for (int i = 0; i < 5;i++){ for (int j = 0; j < 5 - i - 1;j++){ //前面的大于后面的就交换他们的内容 if (strcmp(a[j],a[j+1]) > 0){ strcpy(temp,a[j]); strcpy(a[j],a[j+1]); strcpy(a[j+1],temp); } } } for (int i = 0; i < 5;i++){ printf("a:%s\n",a[i]); } }下面给一个内存图,便于理解,上面的二维数组的内存是在栈中分配的,是一个5行5列的二维数组。因为,这是一个二维字符数组,其实就等价于5个字符串,大小为5(包括'\0')。栈的开口是向下的,一般都是开口向下的栈(地址由高到低,避免栈溢出),当然也有向上的。至于,为什么栈开口向下可以避免溢出,这个原因的话就要从操作系统原理来说了,有兴趣可以自己去学一下,这里就不讨论了。
二、一维指针数组char* a[5]内存模型
void func2(){ //一维指针数组,数组中是一级指针 char* a[3] = {0}; //给数组中的指针开辟空间 for (int i = 0; i < 3;i++){ if (a[i]==NULL){ //数组的大小为5 a[i] = (char*)malloc(5 * sizeof(char)); } } //给数组赋值 strcpy(a[0], "1234");//给a[0]赋值的时候,需要注意,不要a[0]="abcd",不然后面使用strcpy的时候会报异常 //原因,因为,如果你这样赋值,相当于"abcd"是一个常量区中的字符串,只是后把,这个字符串的首地址给a[0], //你是无法改变常量区中的内容 strcpy(a[1], "avxd"); strcpy(a[2], "zcsa"); //对二维数组a进行排序,由大到小进行排序 //第一种,交换它们的内容,利用冒泡排序 char temp[5] = { 0 }; for (int i = 0; i < 3; i++){ for (int j = 0; j < 3 - i - 1; j++){ //前面的大于后面的就交换他们的内容 if (strcmp(a[j + 1], a[j]) > 0){ //这里交换的是指针所指向的内容 strcpy(temp, a[j]); strcpy(a[j], a[j + 1]); strcpy(a[j + 1], temp); } } } for (int i = 0; i < 3;i++){ printf("a:%s\n",a[i]); } strcpy(a[0], "2341"); strcpy(a[0], "a341"); strcpy(a[0], "z341"); //第二种,交换它们的地址,利用冒泡排序 char* ptemp = NULL; for (int i = 0; i < 3; i++){ for (int j = 0; j < 3 - i - 1; j++){ //前面的大于后面的就交换他们的内容 if (strcmp(a[j + 1], a[j]) > 0){ //这里交换的是指针的值 ptemp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } } for (int i = 0; i < 3; i++){ printf("a:%s\n", a[i]); } }一维指针数组内存模型图,这个地址我是随便写的
三、二级指针char** p内存模型
void func3(){ char **a = NULL; a = (char**)malloc(sizeof(char*)*3); for (int i = 0; i < 3;i++){ a[i] = (char*)malloc(sizeof(char)*5); } strcpy(a[0],"1234"); strcpy(a[1],"abcd"); strcpy(a[2],"mnnm"); //对二维数组a进行排序,由大到小进行排序 //第一种,交换它们的内容,利用冒泡排序 char temp[5] = { 0 }; for (int i = 0; i < 3; i++){ for (int j = 0; j < 3 - i - 1; j++){ //前面的大于后面的就交换他们的内容 if (strcmp(a[j + 1], a[j]) > 0){ //这里交换的是指针所指向的内容 strcpy(temp, a[j]); strcpy(a[j], a[j + 1]); strcpy(a[j + 1], temp); } } } for (int i = 0; i < 3; i++){ printf("a:%s\n", a[i]); } strcpy(a[0], "1234"); strcpy(a[1], "9898"); strcpy(a[2], "abcd"); //对二维数组a进行排序,由大到小进行排序 //第二种,交换它们的地址,利用冒泡排序 char* p = (char*)malloc(sizeof(char)*5); for (int i = 0; i < 3; i++){ for (int j = 0; j < 3 - i - 1; j++){ //前面的大于后面的就交换他们的内容 if (strcmp(a[j+1],a[j]) > 0){ //这里交换的是指针所指向的内容 p = a[j]; a[j] = a[j + 1]; a[j + 1] = p; } } } for (int i = 0; i < 3; i++){ printf("a:%s\n", a[i]); } } 二级指针内存模型图,地址是随便写的一个8位十六进制