一、二级指针做输入的第一种内存模型--指针数组
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void PrintMyArray(char **myArray, int num)
{
int i = 0;
for (i = 0; i<num; i++)
{
printf("%s \n", myArray[i]); //等价于printf("%s \n", *(myArray + i));
}
}
void SortMyArray(char **myArray, int num)
{
int i = 0, j = 0;
char *tmp = NULL;
for (i = 0; i<num; i++)
{
for (j = i; j<num; j++)
{
if (strcmp(myArray[i], myArray[j]) > 0)
{
//注意 交换的是数组元素 交换的是指针的值 //改变指针的指向
tmp = myArray[i];
myArray[i] = myArray[j];
myArray[j] = tmp;
}
}
}
}
int main()
{
int i = 0, j = 0, num = 0;
char *tmp = NULL;
//数组 数组中的每一个元素是指针 指针数组
char *myArray[] = { "aDDDGHJK", "ccccc", "bbbbbb", "111111" };
//打印
num = sizeof(myArray) / sizeof(myArray[0]);//指针也是一种数据类型,是指指针所指向的内存空间的数据类型
printf("排序之前\n");
PrintMyArray(myArray, num);
SortMyArray(myArray, num);
printf("排序之后\n");
PrintMyArray(myArray, num);
system("pause");
return;
}
上面代码中myArray是一个数组,其每一个元素都是一个指针,我们将其称作指针数组,myArray是一个二级指针。myArray 是数组的首地址,在栈上分配内存。
我们对数组进行分析,画出其内存模型,我们通过内存模型发现,我们在排序时,交换的确实是指针的值,改变了指针的指向。
二、二级指针做输入的第二种内存模型--二维数组
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//错误的本质:二级指针做输入_第2种内存模型 的 myArray + 1与
//二级指针做输入_第1种内存模型的myArray + 1 不一样 ;
//指针的步长不一样 指针所指向的内存空间的数据类不一样 。。。。
void printMyArray02_err(char **myArray, int num)
{
int i = 0;
for (i = 0; i<num; i++)
{
//printf("%s \n", myArray[i]);
printf("%s \n", *(myArray + i)); //
}
}
void printMyArray02(char myArray[10][30], int num)
{
int i = 0;
for (i = 0; i<num; i++)
{
//printf("%s \n", myArray[i]);
printf("%s \n", *(myArray + i)); //
}
}
//交换的是内存块。。。。。。。。
void sortMyArray02(char myArray[10][30], int num)
{
int i, j = 0;
char tmpBuf[30];
for (i = 0; i<num; i++)
{
for (j = i + 1; j<num; j++)
{
if (strcmp(myArray[i], myArray[j]) > 0)
{
strcpy(tmpBuf, myArray[i]); //交换的是内存块
strcpy(myArray[i], myArray[j]);
strcpy(myArray[j], tmpBuf);
}
}
}
}
void main()
{
int i = 0, j = 0;
int num = 4;
char myBuf[30];
char tmpBuf[30];
char myArray[10][30] = { "aaaaaa", "ccccc", "bbbbbbb", "111111" }; //多维数组
{
int len1 = sizeof(myArray); //编译器对myArray分配10*30内存
int len2 = sizeof(myArray[0]); //编译器对myArray[i]分配10
int size = len1 / len2;
printf("len1:%d , len2:%d size:%d \n", len1, len2, size);
}
//打印
printf("排序之前\n");
printMyArray02(myArray, num);
sortMyArray02(myArray, num);
//打印
printf("排序之后\n");
printMyArray02(myArray, num);
printf("hello...\n");
system("pause");
return;
}
输出:
len1:300 , len2:30 size:10
排序之前
aaaaaa
ccccc
bbbbbbb
111111
排序之后
111111
aaaaaa
bbbbbbb
ccccc
hello...
请按任意键继续. . .
者个代码里面myArray是一个二维数组,二维数组也是一个二级指针,不过因为其编译器对其在栈上编译的时候就已经分配了内存。
而且我们的打印函数此时以**myArray做函数参数是会报错的,因为在这个函数里面有myArray+1这个语句,
printMyArray02_err(char **myArray, int num)
myArray+1对于指针数组来讲,每次+1 都是数组的下标+1 每次指向的都是一个独立的字符串,内存地址改变4(sizeof(char)=4)字节。而对于二维数组来讲,每次+1 内存地值改变 sizeof(myArray[i]) 个字节。
当然二维数组做函数参数并不是这么简单,我们后面后进行更深入的讨论,这里主要要明白的是二维数组做输入时的内存模型。
扫描二维码关注公众号,回复:
2588285 查看本文章
三、二级指针做输入的第三种内存模型
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void PrintArray(char **str,int num)
{
char**tmp = NULL;
if (str == NULL || num == 0)
{
return -1;
}
else
{
tmp = str;
for ( int i = 0; i < num; i++)
{
printf("%s\n", tmp[i]);
}
}
}
//通过交换指针的值进行从大到小排序
void SortedArray1(char **str,int num)
{
char **tmp = NULL;
char *sort = NULL;
if (str == NULL || num == 0)
{
return -1;
}
else
{
tmp = str;
for (int i = 0; i <num;i++)
for (int j = i + 1; j < num; j++)
{
if (strcmp(tmp[i],tmp[j])<1)
{
sort = tmp[i];
tmp[i] = tmp[j];
tmp[j] = sort;
}
}
}
}
//通过交换指针所指向内存空间的地址进行从小到大排序
void SortedArray2(char **str, int num)
{
char **tmp = NULL;
char sort[10] = { 0 };
if (str == NULL || num == 0)
{
return -1;
}
else
{
tmp = str;
for (int i = 0; i < num; i++)
for (int j = i+1; j < num; j++)
{
if (strcmp(tmp[i], tmp[j])>1)
{
strcpy(sort, tmp[i]);
strcpy(tmp[i], tmp[j]);
strcpy(tmp[j], sort);
}
}
}
}
//三级指针做函数参数,可以去修改二级指针的值
void DelArray(char ***str,int num)
{
char ***tmp = NULL;
if (str == NULL || num == 0)
{
return -1;
}
else
{
tmp = str;
for (int i = 0; i < num; i++)
{
if (*((*tmp)+i) != NULL)
{
free(*((*tmp) + i));
*((*tmp) + i) = NULL;
}
}
free(*tmp);
*tmp = NULL;
}
}
void main()
{
int i = 0, j = 0,num = 5;
char **p = NULL;//用来存放指针地址的指针,因此是一个二级指针,在栈上分配内存。
p = (char**)malloc(sizeof(char*)*num);//p1指针指向的内存包含有num个指针类型的数据
//对p1指针指向的内存中的num指针指向的内存分配内存单元,并拷贝数据。
for (i = 0; i<5; i++)
{
p[i] = (char*)malloc(sizeof(char) * 10); //分配10个字节的内存
sprintf(p[i], "%d%d",i,i);
}
printf("未排序之前\n");
PrintArray(p,num);
SortedArray1(p,num);
printf("指针值排序\n");
PrintArray(p,num);
printf("内存数据排序\n");
SortedArray2(p, num);
PrintArray(p, num);
DelArray(&p, num);
printf("%s\n", p);
printf("hello...\n");
system("pause");
return;
}
我们先对mian函数的第一个printf之前的代码,进行内存分析。
因为内存模型的关系,我们可以使用两种方式对其进行排序。最后按照先申请的内存后释放的原则,将所有的malloc堆上的内存释放,并将指针变为NULL,防止出现野指针。