C语言二级指针做输入的内存模型

一、二级指针做输入的第一种内存模型--指针数组

#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])  个字节。

       当然二维数组做函数参数并不是这么简单,我们后面后进行更深入的讨论,这里主要要明白的是二维数组做输入时的内存模型。

三、二级指针做输入的第三种内存模型

    
#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,防止出现野指针。


猜你喜欢

转载自blog.csdn.net/m0_37717595/article/details/80542719
今日推荐