C语言中指针及其应用高级篇(用指针实现数组的扩增)

一、一级指针与一维数组

把指针充当变量的用法,在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 = &num; 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的运行机制,画图。 在这里插入图片描述 暂时到这里。 **

球球了,给点个赞吧 !(>-<)!

**

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

PhoneGap设置Icon

参考:http://cordova.apache.org/docs/en/latest/config\_ref/images.html通过config.xml中的<icon标签来设置Icon<iconsrc"res/ios/icon.png"platform"ios"width"57"height"57"densi