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

桃浪十七丶
• 阅读 1104

一、一级指针与一维数组

把指针充当变量的用法,在C/C++的数据结构学习中广为应用,这种用法学习起来是比较简单的。 先看代码。这里的代码,有string.h头文件包含的函数,和scanf,这两者在正常的写法中不用加“_s”,这篇随笔所及代码的运行环境是Visual Studio2017,编译器会把scanf等函数增强,因此为了正常运行,会加上“_s”.

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
int main() {

    //把指针充当变量的方式有两种
    //1. 通过变量的地址初始化
    int num = 1;
    int *pInt = &num;
    *pInt = 101;    //这里的*pInt等效于num
    printf("*pInt=%d\tnum=%d\n", *pInt, num);

    //2.1. 通过使用malloc初始化内存,让指针变成普通变量
    int *p = (int *)malloc(sizeof(int));
    if (p == NULL) {
        return 0;
    }
    *p = 101;
    printf("*p=%d\n", *p);
    free(p);
    p = NULL;

    //2.2 可以把指针变成数组,一级指针则成为一维数组 
    int *array = (int *)malloc(sizeof(int ) * 3);
    if (array == NULL) {
        return 0;
    }
    for (int i = 0; i < 3; i++) {
        scanf_s("%d", array + i);    //把从键盘输入的字符存储到数组中
        //array[i] = i;   自动添加数字元素到数组中
        printf("arr[%d]=%d,arr[%d]=%d\n", i, array[i], i, *(array + i));
    }
    free(array);
    array = NULL;

    //3. 指针作为字符数组
    char *pChar = (char *)malloc(sizeof(char) * 27);
    for (int i = 0; i < 26; i++)
    {
        pChar[i] = 'A' + i;
        printf("%c\t", pChar[i]);
    }
    printf("\n");

    //3.1 字符数组,字符串的区别
    pChar[26] = '\0';
    printf("%s\n", pChar);
    printf("\n");
    free(pChar);
    pChar = NULL;

    //3.2 关于字符数组赋值的问题,C语言中没有string类型
    char *pStr = (char *)malloc(sizeof(char) * 10);   //pStr[10];
    /*
        字符串的赋值只能通过两种方式
        1. 字符串采用字符的方式去处理
        2. 通过字符串拷贝函数去赋值
    */
    strcpy(pStr, "Loveyou");
    printf("%s\n", pStr);
    free(pStr);
    pStr = NULL;

    //3.3 申请的数组长度可以为一个变量
    printf("你想输入多少个学生信息:");
    int count = 0;
    scanf_s("%d", &count);
    float *pScore = (float *)malloc(sizeof(float)*count);
    printf("请输入%d个学生成绩\n", count);
    for (int i = 0; i < count; i++)
    {
        scanf("%f", pScore + i);
    }
    for (int i = 0; i < count; i++)
    {
        printf("%f\t", pScore[i]);
    }
    printf("\n");
    free(pScore);
    pScore = NULL;
    system("pause");
    return 0;
}

把指针充当变量的用法有两种: ①:通过变量的得地址初始化; ②通过使用malloc初始化内存,让指针变成普通变量。

1.1通过变量的地址初始化

如代码中1.1的例子所写,定义一个普通变量并初始化,然后定义一个指针变量,通过取地址符号取到普通变量num的值,赋值给指针,此时指针变量 *pInt等效于变量num,在后面修改num的值的时候可以直接用指针变量来修改。这部分其实没什么好讲的,很简单。

2.1使用malloc函数使指针变量变成普通变量

申请一个存储int类型变量的内存,写法大概的如下:

int *p = (int *)malloc(sizeof(int));

格式: 基本数据类型 *指针变量名 = (强制转换类型)malloc(sizeof(基本数据类型)) 注意两点: ① 在正式编程中我们要用防御式编程的思想; ②在申请且使用了内存后,要及时释放内存,释放步骤为

  free(指针变量名字);
  指针变量名=NULL;

2.2使用 malloc申请一段内存

方式大概如下:

int *array = (int *)malloc(sizeof(int ) * 3);

格式: 基本数据类型 指针变量名 = (强制转换类型)malloc(sizeof(基本数据类型)需要申请的长度) 在例子2.2中,再复习一遍之前学过的内容,用array[i]和*(array+i)两种方式分别遍历一遍整形数组。

2.3 使用malloc申请字符类型的内存

方式大概如下:

char *pChar = (char *)malloc(sizeof(char) * 27);

我们用26个字母作为字符数组遍历。 这里需要注意的是: ①C语言中,字符数组是按照字符串来处理的; ②字符串的末尾,需要在字符串最后一位加上"\0"来结尾; ③字符数组和字符串是有区别的,因此用 %c而不是%s ④申请字符类型空时,代码中的27可以用变量替换掉。如替换成count。 第二条,我们可以把循环遍历中的

printf("%c\t", pChar[i]);
pChar[26] = '\0';

这两行代码用注释掉和不注释两种情况来比较,得出结论,如下两张图。 注释掉后的结果: C语言中指针及其应用高级篇(用指针实现数组的扩增) 不注释的结果: C语言中指针及其应用高级篇(用指针实现数组的扩增) 明显的,在注释掉循环中的打印代码后,通过比较有无字符串结尾处理得出结论。 第四条的写法,如上面代码所示,这一部分没有需要注意的东西,不做阐述。

二、二级指针与二维数组

这里说明,二级指针并不能直接转成二维数组,二维数组中的元素都是普通变量,而二级指针指向的地址,存储的是一级指针变量的地址。 附上一张图 C语言中指针及其应用高级篇(用指针实现数组的扩增)

这部分的讲解基本都在代码块的注释里,复制到文本文件里食用口味更加。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//1.2  通过返回值申请内存,这是一个申请数组的函数
int *Mallo_Array(int arrLength) {
    int *array = (int *)malloc(sizeof(int *)*arrLength);
    return array;    //返回数组首地址
}
//1.3  通过参数申请内存
void  malloc_Array1D(int **array, int arrLen) {
    //通过一级指针修改普通变量的值,因此改变普通变量时候传递一级指针
    //通过二级指针修改一级指针的指针变量,因此改变指针指向的时候要传递二级指针
    *array = (int *)malloc(sizeof(int  *)*arrLen);
}

//1.4  字符串当做函数参数,申请内存
//通过外部变量来初始化字符串,如申请一个内存存储字符串,可能传一个常量,而常量是不能修改的,因此要申请一段内存来保存常量
//这里不用malloc而是用 strlen,因为fileName只是一个指针,用malloc申请到的永远是4个字节
void malloc_String(const char *fileName) {
    char *pStr = (char *)malloc(strlen(fileName) + 1);        //计算长度,此处字符串数组长度要+1
    strcpy(pStr,fileName);        //使用strcpy来赋值,把fileName拷贝到pStr中就可以对fileName进行修改操作
    printf("%s", pStr);
}


int main() {
    //1.1 二级指针和二维数组
    int *pInt = (int *)malloc(sizeof(int) * 3);        //意味着每一个SecPointer[i]都是一个一级指针
    int **SecPointer = (int **)malloc(sizeof(int *) * 9);    //开辟九个长度的存放一级指针变量的数组
    for (int i = 0; i < 9; i++) {
        SecPointer[i] = (int *)malloc(sizeof(int) * 9);        //为九个指针申请内存使其成为二维数组
    }
    SecPointer[7][7] = 101;
    printf("%d\n", SecPointer[7][7]);
    free(SecPointer);
    SecPointer = NULL;

    //1.2  调用函数申请一个容量为3的一维数组
    int *array = Mallo_Array(3);
    for (int i = 0; i < 3; i++) {
        array[i] = i;
        printf("array[%d]=%d,array[%d]=%d\n", i, *(array+i),i,array[i]);
    }
    free(array);
    array = NULL;

    //1.4
    malloc_String("LoveYou");
    printf("\n");
    system("pause");
    return 0;
}

下面是运行结果。 C语言中指针及其应用高级篇(用指针实现数组的扩增)

三、malloc,realloc,calloc

上代码。

#include<stdio.h>
#include<stdlib.h>

//1.1  calloc函数在申请内存后会默认初始化 
//1.2  realloc函数可在内存不足的情况下重新申请内存,且具有复制功能,即会把原来内存里的元素再复制到新申请的内存中

int main() {
    //1.1
    int *pCalloc = (int *)calloc(3, sizeof(int));
    int *pMalloc = (int *)malloc(sizeof(int) * 3);
    for (int i = 0; i < 3; i++) {
        printf("Calloc[%d]=%d\n", i, pCalloc[i]);
    }
    printf("\n");
    free(pCalloc);
    pCalloc = NULL;
    for (int j = 0; j < 3; j++) {
        printf("Malloc[%d]=%d\n", j, pMalloc[j]);
    }
    printf("\n");
    free(pMalloc);
    pMalloc = NULL;

    //1.2
    int *pMall = (int *)malloc(sizeof(int) * 3);
    for (int x = 0; x < 3; x++) {
        pMall[x] = x;
    }
    realloc(pMall, sizeof(int) * 6);
    for (int y = 3; y < 6; y++) {
        pMall[y] = y;
    }
    for (int z = 0; z < 6; z++) {
        printf("%d", pMall[z]);
    }
    system("pause");
    return 0;
}

需要注意的是realloc,calloc,malloc在写法上的不同 ,三者分别两两放在一起比较:

int *pCalloc = (int *)calloc(3, sizeof(int));
int *pMalloc = (int *)malloc(sizeof(int) * 3);
int *pMall = (int *)malloc(sizeof(int) * 3);
realloc(pMall, sizeof(int) * 6);

可以看到calloc函数和malloc在申请内存时候的写法,只在后面部分的顺序不同;而realloc和malloc相比,则有很大的不同,这是因为他们的功能上有很大的差别: ①malloc:申请内存,不进行初始化; ②calloc:申请内存,并进行初始化,初始化为0; ③realloc:当之前申请的内存不足时候,重新申请内存,且申请的内存应为原来内存的整数倍。realloc在申请内存后,会把原内存的内容复制到新内存中。 下面是运行结果。 C语言中指针及其应用高级篇(用指针实现数组的扩增)

显而可见,calloc会自动将数组中的内容初始化为0,而malloc不会。在实际应用中,malloc的应用会比calloc多得多。而realloc通过使用前和使用后两种情况,将其打印输出,也可以很清晰的了解其功能。 为了更加清楚地明白realloc的运行机制,画图。 C语言中指针及其应用高级篇(用指针实现数组的扩增) 暂时到这里。 **

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

**

点赞
收藏
评论区
推荐文章
Jacquelyn38 Jacquelyn38
1年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。 1、使用解构获取json数据let jsonData   id: 1, status: "OK", data: ['a', 'b'] ; let  id, status, data: number   jsonData; console.log(id, status, number )
blmius blmius
1年前
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:SQL Mode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。 全局s
Stella981 Stella981
11个月前
PhoneGap设置Icon
参考:http://cordova.apache.org/docs/en/latest/config\_ref/images.html 通过config.xml中的<icon>标签来设置Icon <icon src="res/ios/icon.png" platform="ios" width="57" height="57" densi
Stella981 Stella981
11个月前
KVM调整cpu和内存
一.修改kvm虚拟机的配置 1、virsh edit centos7 找到“memory”和“vcpu”标签,将 <name>centos7</name> <uuid>2220a6d1-a36a-4fbb-8523-e078b3dfe795</uuid>
Wesley13 Wesley13
11个月前
MySQL总结(十一)子查询
![](https://oscimg.oschina.net/oscnet/up-a344f41e81d3568e3310b5da00c57ced8ea.png) 子查询 === * * * 1\. 什么是子查询 ---------- -- 需求:查询开发部中有哪些员工 select * from emp; -- 通
Easter79 Easter79
11个月前
Twitter的分布式自增ID算法snowflake (Java版)
概述 == 分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。 有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。 而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
11个月前
MySQL查询按照指定规则排序
1.按照指定(单个)字段排序 select * from table_name order id desc; 2.按照指定(多个)字段排序 select * from table_name order id desc,status desc; 3.按照指定字段和规则排序 selec
Stella981 Stella981
11个月前
Angular material mat
Icon Icon Name mat-icon code _add\_comment_ add comment icon <mat-icon> add\_comment</mat-icon> _attach\_file_ attach file icon <mat-icon> attach\_file</mat-icon> _attach\
Wesley13 Wesley13
11个月前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
#### 背景描述 # Time: 2019-01-24T00:08:14.705724+08:00 # User@Host: **[**] @ [**] Id: ** # Schema: sentrymeta Last_errno: 0 Killed: 0 # Query_time: 0.315758 Lock_
helloworld_34035044 helloworld_34035044
2个月前
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。 uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid() 或 uuid(sep)参数说明:sep 布尔值,生成的uuid中是否包含分隔符'',缺省为