一、一级指针与一维数组
把指针充当变量的用法,在C/C++的数据结构学习中广为应用,这种用法学习起来是比较简单的。 先看代码。这里的代码,有string.h头文件包含的函数,和scanf,这两者在正常的写法中不用加“_s”,这篇随笔所及代码的运行环境是Visual Studio2017,编译器会把scanf等函数增强,因此为了正常运行,会加上“_s”.
1#define _CRT_SECURE_NO_WARNINGS 2#include<stdio.h> 3#include<stdlib.h> 4#include<string.h> 5#include<malloc.h> 6int main() { 7 8 //把指针充当变量的方式有两种 9 //1. 通过变量的地址初始化 10 int num = 1; 11 int *pInt = # 12 *pInt = 101; //这里的*pInt等效于num 13 printf("*pInt=%d\tnum=%d\n", *pInt, num); 14 15 //2.1. 通过使用malloc初始化内存,让指针变成普通变量 16 int *p = (int *)malloc(sizeof(int)); 17 if (p == NULL) { 18 return 0; 19 } 20 *p = 101; 21 printf("*p=%d\n", *p); 22 free(p); 23 p = NULL; 24 25 //2.2 可以把指针变成数组,一级指针则成为一维数组 26 int *array = (int *)malloc(sizeof(int ) * 3); 27 if (array == NULL) { 28 return 0; 29 } 30 for (int i = 0; i < 3; i++) { 31 scanf_s("%d", array + i); //把从键盘输入的字符存储到数组中 32 //array[i] = i; 自动添加数字元素到数组中 33 printf("arr[%d]=%d,arr[%d]=%d\n", i, array[i], i, *(array + i)); 34 } 35 free(array); 36 array = NULL; 37 38 //3. 指针作为字符数组 39 char *pChar = (char *)malloc(sizeof(char) * 27); 40 for (int i = 0; i < 26; i++) 41 { 42 pChar[i] = 'A' + i; 43 printf("%c\t", pChar[i]); 44 } 45 printf("\n"); 46 47 //3.1 字符数组,字符串的区别 48 pChar[26] = '\0'; 49 printf("%s\n", pChar); 50 printf("\n"); 51 free(pChar); 52 pChar = NULL; 53 54 //3.2 关于字符数组赋值的问题,C语言中没有string类型 55 char *pStr = (char *)malloc(sizeof(char) * 10); //pStr[10]; 56 /* 57 字符串的赋值只能通过两种方式 58 1. 字符串采用字符的方式去处理 59 2. 通过字符串拷贝函数去赋值 60 */ 61 strcpy(pStr, "Loveyou"); 62 printf("%s\n", pStr); 63 free(pStr); 64 pStr = NULL; 65 66 //3.3 申请的数组长度可以为一个变量 67 printf("你想输入多少个学生信息:"); 68 int count = 0; 69 scanf_s("%d", &count); 70 float *pScore = (float *)malloc(sizeof(float)*count); 71 printf("请输入%d个学生成绩\n", count); 72 for (int i = 0; i < count; i++) 73 { 74 scanf("%f", pScore + i); 75 } 76 for (int i = 0; i < count; i++) 77 { 78 printf("%f\t", pScore[i]); 79 } 80 printf("\n"); 81 free(pScore); 82 pScore = NULL; 83 system("pause"); 84 return 0; 85}
把指针充当变量的用法有两种: ①:通过变量的得地址初始化; ②通过使用malloc初始化内存,让指针变成普通变量。
1.1通过变量的地址初始化
如代码中1.1的例子所写,定义一个普通变量并初始化,然后定义一个指针变量,通过取地址符号取到普通变量num的值,赋值给指针,此时指针变量 *pInt等效于变量num,在后面修改num的值的时候可以直接用指针变量来修改。这部分其实没什么好讲的,很简单。
2.1使用malloc函数使指针变量变成普通变量
申请一个存储int类型变量的内存,写法大概的如下:
1int *p = (int *)malloc(sizeof(int));
格式: *基本数据类型 指针变量名 = (强制转换类型)malloc(sizeof(基本数据类型)) 注意两点: ① 在正式编程中我们要用防御式编程的思想; ②在申请且使用了内存后,要及时释放内存,释放步骤为
1 free(指针变量名字); 2 指针变量名=NULL;
2.2使用 malloc申请一段内存
方式大概如下:
1int *array = (int *)malloc(sizeof(int ) * 3);
格式: *基本数据类型 指针变量名 = (强制转换类型)malloc(sizeof(基本数据类型)需要申请的长度) 在例子2.2中,再复习一遍之前学过的内容,用array[i]和(array+i)两种方式分别遍历一遍整形数组。
2.3 使用malloc申请字符类型的内存
方式大概如下:
1char *pChar = (char *)malloc(sizeof(char) * 27);
我们用26个字母作为字符数组遍历。 这里需要注意的是: ①C语言中,字符数组是按照字符串来处理的; ②字符串的末尾,需要在字符串最后一位加上"\0"来结尾; ③字符数组和字符串是有区别的,因此用 %c而不是%s ④申请字符类型空时,代码中的27可以用变量替换掉。如替换成count。 第二条,我们可以把循环遍历中的
1printf("%c\t", pChar[i]); 2pChar[26] = '\0';
这两行代码用注释掉和不注释两种情况来比较,得出结论,如下两张图。
注释掉后的结果:
不注释的结果:
明显的,在注释掉循环中的打印代码后,通过比较有无字符串结尾处理得出结论。
第四条的写法,如上面代码所示,这一部分没有需要注意的东西,不做阐述。
二、二级指针与二维数组
这里说明,二级指针并不能直接转成二维数组,二维数组中的元素都是普通变量,而二级指针指向的地址,存储的是一级指针变量的地址。
附上一张图

这部分的讲解基本都在代码块的注释里,复制到文本文件里食用口味更加。
1#define _CRT_SECURE_NO_WARNINGS 2#include<stdio.h> 3#include<stdlib.h> 4#include<string.h> 5 6//1.2 通过返回值申请内存,这是一个申请数组的函数 7int *Mallo_Array(int arrLength) { 8 int *array = (int *)malloc(sizeof(int *)*arrLength); 9 return array; //返回数组首地址 10} 11//1.3 通过参数申请内存 12void malloc_Array1D(int **array, int arrLen) { 13 //通过一级指针修改普通变量的值,因此改变普通变量时候传递一级指针 14 //通过二级指针修改一级指针的指针变量,因此改变指针指向的时候要传递二级指针 15 *array = (int *)malloc(sizeof(int *)*arrLen); 16} 17 18//1.4 字符串当做函数参数,申请内存 19//通过外部变量来初始化字符串,如申请一个内存存储字符串,可能传一个常量,而常量是不能修改的,因此要申请一段内存来保存常量 20//这里不用malloc而是用 strlen,因为fileName只是一个指针,用malloc申请到的永远是4个字节 21void malloc_String(const char *fileName) { 22 char *pStr = (char *)malloc(strlen(fileName) + 1); //计算长度,此处字符串数组长度要+1 23 strcpy(pStr,fileName); //使用strcpy来赋值,把fileName拷贝到pStr中就可以对fileName进行修改操作 24 printf("%s", pStr); 25} 26 27 28int main() { 29 //1.1 二级指针和二维数组 30 int *pInt = (int *)malloc(sizeof(int) * 3); //意味着每一个SecPointer[i]都是一个一级指针 31 int **SecPointer = (int **)malloc(sizeof(int *) * 9); //开辟九个长度的存放一级指针变量的数组 32 for (int i = 0; i < 9; i++) { 33 SecPointer[i] = (int *)malloc(sizeof(int) * 9); //为九个指针申请内存使其成为二维数组 34 } 35 SecPointer[7][7] = 101; 36 printf("%d\n", SecPointer[7][7]); 37 free(SecPointer); 38 SecPointer = NULL; 39 40 //1.2 调用函数申请一个容量为3的一维数组 41 int *array = Mallo_Array(3); 42 for (int i = 0; i < 3; i++) { 43 array[i] = i; 44 printf("array[%d]=%d,array[%d]=%d\n", i, *(array+i),i,array[i]); 45 } 46 free(array); 47 array = NULL; 48 49 //1.4 50 malloc_String("LoveYou"); 51 printf("\n"); 52 system("pause"); 53 return 0; 54}
下面是运行结果。

三、malloc,realloc,calloc
上代码。
1#include<stdio.h> 2#include<stdlib.h> 3 4//1.1 calloc函数在申请内存后会默认初始化 5//1.2 realloc函数可在内存不足的情况下重新申请内存,且具有复制功能,即会把原来内存里的元素再复制到新申请的内存中 6 7int main() { 8 //1.1 9 int *pCalloc = (int *)calloc(3, sizeof(int)); 10 int *pMalloc = (int *)malloc(sizeof(int) * 3); 11 for (int i = 0; i < 3; i++) { 12 printf("Calloc[%d]=%d\n", i, pCalloc[i]); 13 } 14 printf("\n"); 15 free(pCalloc); 16 pCalloc = NULL; 17 for (int j = 0; j < 3; j++) { 18 printf("Malloc[%d]=%d\n", j, pMalloc[j]); 19 } 20 printf("\n"); 21 free(pMalloc); 22 pMalloc = NULL; 23 24 //1.2 25 int *pMall = (int *)malloc(sizeof(int) * 3); 26 for (int x = 0; x < 3; x++) { 27 pMall[x] = x; 28 } 29 realloc(pMall, sizeof(int) * 6); 30 for (int y = 3; y < 6; y++) { 31 pMall[y] = y; 32 } 33 for (int z = 0; z < 6; z++) { 34 printf("%d", pMall[z]); 35 } 36 system("pause"); 37 return 0; 38}
需要注意的是realloc,calloc,malloc在写法上的不同 ,三者分别两两放在一起比较:
1int *pCalloc = (int *)calloc(3, sizeof(int)); 2int *pMalloc = (int *)malloc(sizeof(int) * 3);
1int *pMall = (int *)malloc(sizeof(int) * 3); 2realloc(pMall, sizeof(int) * 6);
可以看到calloc函数和malloc在申请内存时候的写法,只在后面部分的顺序不同;而realloc和malloc相比,则有很大的不同,这是因为他们的功能上有很大的差别:
①malloc:申请内存,不进行初始化;
②calloc:申请内存,并进行初始化,初始化为0;
③realloc:当之前申请的内存不足时候,重新申请内存,且申请的内存应为原来内存的整数倍。realloc在申请内存后,会把原内存的内容复制到新内存中。
下面是运行结果。

显而可见,calloc会自动将数组中的内容初始化为0,而malloc不会。在实际应用中,malloc的应用会比calloc多得多。而realloc通过使用前和使用后两种情况,将其打印输出,也可以很清晰的了解其功能。
为了更加清楚地明白realloc的运行机制,画图。
暂时到这里。
**
球球了,给点个赞吧 !(>-<)!
**
