C语言进阶:动态分配内存,二维指针

文章目录

  • 动态分配内存
    • 1.数组空间申请
    • 2.重新调整内存大小
    • 3. 数组的整体拷贝、比较、移动
  • 二维指针
    • 1. 二维指针的用法
    • 2. 动态内存创建二维数组

动态分配内存

1.数组空间申请

申请动态分配内存 malloc()
stdlib.h 中定义函数 void* malloc(size_t size)
向系统申请大小为 size 的内存空间
返回结果是 void*,使用时转换成需要的指针类型
如果申请失败,返回 NULL

向系统申请一块 n*4 字节的空间
(int*)malloc(n*sizeof(int))

#include 
#include 

int main(){
        int n;
        scanf("%d",&n);
        // 等同于 int arr[n];
        int* arr = malloc(n*sizeof(int));
        for(int i=0;i<n;++i){
                scanf("%d",arr+i);
        }
        for(int i=0;i<n;++i){
                printf("%d ",arr[i]);
        }
        printf("\n");

        free(arr);   // 释放指针
        arr = NULL;
}

结果为:

5
1 2 3 4 5
1 2 3 4 5 

释放动态分配内存 free()
注意 free() 的问题:
已经释放了,但每清空,就会形成野指针,野指针如果再次使用,就会报错

另外还有一个函数
calloc(n,sizeof(int))
格式与 malloc() 不同,但作用和 malloc() 相同

2.重新调整内存大小

函数 作用
malloc() 分配内存块,不初始化
calloc() 分配内存块,初始化为0
realloc() 调整先前分配的内存块大小
free() 释放分配内存块

从终端输入未知个数的数字,用ctrl+d结束,并输出所有输入的数

#include 
#include 

int main(){
        int* arr = NULL;
        int count = 0;
        for(;;){
                int m;
                int res = scanf("%d",&m);
                // 输入结束会返回EOF,为Ctrl+z 或者Ctrl+d
                if(EOF == res) break;
                /*
                if(count == 0){
                        arr = calloc(1,sizeof(int));
                }else{
                        arr = realloc(arr,sizeof(int)*(count+1));
                }
                */
                // 当 arr == NULL 时,realloc() 相当于 malloc()
                arr = realloc(arr,sizeof(int)*(count+1));
                arr[count] = m;
                ++count;
        }

        for(int i=0;i<count;++i){
                printf("%d ",arr[i]);
        }
        printf("\n");

        free(arr);
        arr = NULL;
}

结果为:

1 2 3 4 5 6
7 6 5 4 3 2
1 2 3
1 2 3 4 5 6 7 6 5 4 3 2 1 2 3 

3. 数组的整体拷贝、比较、移动

函数 含义
memset() 填充内存
memcpy() 内存拷贝
memmove() 内存移动
memcmp() 内存比较
memchr() 查找内存中第一个出现指定字符的位置

例如: memcpy(拷给谁,从谁那拷,拷的字节数);

给数组赋值,比较数组,移动数组:

#include 
#include 

int main(){
        int arr1[] = {1,2,3,4,5};
        int arr2[5];
        /*
        for(int i=0;i<5;++i){
                arr2[i] = arr1[i];
        }
        */
        // 把arr1的值拷贝到arr2中
        memcpy(arr2,arr1,sizeof(arr1));
        for(int i=0;i<5;++i){
                printf("%d ",arr2[i]);
        }
        printf("\n");

        // arr1和arr2做比较
        arr2[3] = 9;
        if(memcmp(arr1,arr2,sizeof(arr1)) == 0){
                printf("相等\n");
        }else{
                printf("不相等\n");
        }

        // arr1成员向前移一个
        memmove(arr1,arr1+1,4*sizeof(int));
        for(int i=0;i<5;++i){
                printf("%d ",arr1[i]);
        }
        printf("\n");
}

结果为:

1 2 3 4 5 
不相等
2 3 4 5 5 

二维指针

1. 二维指针的用法

传入一维指针地址可以取出函数内部申请的单个变量的动态内存

理解二维指针作为函数参数:

#include 
#include 

void Func(int** pp){
        *pp = malloc(sizeof(int));
        **pp = 100;
        printf("%p\n",*pp);
        printf("%d\n",**pp);
}

int main(){
        int* p = NULL;
        Func(&p);
        printf("%p\n",p);
        printf("%d\n",*p);

        free(p);
        p = NULL;
}

结果为:

0x9a42a0
100
0x9a42a0
100

首先,malloc() 需要把内存传给一个指针,其次,无返回值函数传参本身就需要通过指针保证修改的解引用是一个东西,所以,要用到二维指针

有返回参数的情况:

#include 
#include 

int* Func2(){
        int* p = malloc(sizeof(int));
        *p = 200;
        printf("%p\n",p);
        printf("%d\n",*p);

        return p;
}

int main(){
        int* p = NULL;
        p = Func2();
        printf("%p\n",p);
        printf("%d\n",*p);

        free(p);
        p = NULL;
}

结果为:

0x19ca2a0
200
0x19ca2a0
200

传入一维指针地址也可以取出函数内部申请的一个数组的动态内存

函数传参方式打印函数中数组后:

#include 
#include 

void Func(int** pp){
        *pp = malloc(sizeof(int)*10);
        for(int i=0;i<10;++i){
                (*pp)[i] = i;
        }
}

int main(){
        int* p = NULL;
        Func(&p);

        for(int i=0;i<10;++i){
                printf("%d ",p[i]);
        }
        printf("\n");

        free(p);
        p = NULL;
}

结果为:

0 1 2 3 4 5 6 7 8 9 

2. 动态内存创建二维数组

可以把二维数组 arr[n][m]
想成 n 个一维数组 arr[m]
申请 n 个一维数组内存空间 malloc(m*sizeof(int));
再给这 n 个内存指针申请一个空间 malloc(n*sizeof(int*))

动态内存创建二维数组:

#include 
#include 

int main(){
        int n,m;
        scanf("%d%d",&n,&m);
        int** parr = malloc(n*sizeof(int*));
        for(int i=0;i<n;++i){
                parr[i] = malloc(m*sizeof(int));
                for(int j=0;j<m;++j){
                        scanf("%d",&parr[i][j]);
                }
        }

        for(int i=0;i<n;++i){
                for(int j=0;j<m;++j){
                        printf("%d ",parr[i][j]);
                }
                printf("\n");
        }

        for(int i=0;i<n;++i){
                free(parr[i]);
                parr[i] = NULL;
        }
        free(parr);
        parr = NULL;
}

结果为:

2 3
1 2 3
4 5 6
1 2 3 
4 5 6 

malloc 把新建的空间给那个指针,就要用 free 释放哪个指针

练习题:

  1. 实现函数 swapString() ,交换两个字符串的值
#include 

void swapString(char** pa,char** pb){
        char* t = *pa;
        *pa = *pb;
        *pb = t;
}

int main(){
        char* a = "123";
        char* b = "abcd";
        printf("a:%s\n",a);
        printf("b:%s\n",b);
        swapString(&a,&b);
        printf("a:%s\n",a);
        printf("b:%s\n",b);
}

结果为:

a:123
b:abcd
a:abcd
b:123
  1. 实现函数输入正数n,返回三角星号图像字符串数组
#include 
#include 

int main(){
        int n;
        scanf("%d",&n);

        char** res = malloc(n*sizeof(char*));
        for(int i=0;i<n;++i){
                res[i] = calloc(i+2,sizeof(char));   // 包括\0
                for(int j=0;j<=i;++j){
                        res[i][j] = '*';
                }
        }

        for(int i=0;i<n;++i){
                printf("%s\n",res[i]);
        }

        for(int i=0;i<n;++i){
                free(res[i]);
                res[i] = NULL;
        }
        free(res);
        res = NULL;
}

结果为:

4
*
**
***
****
  1. 实现函数输入正数n和m,返回n~m行随机行随机列的星号图像字符串数组
#include 
#include 
#include 

int main(){
        int n,m;
        scanf("%d%d",&n,&m);
        // 生成随机数
        srand(time(NULL));

        // 要n~m的数
        int row = rand()%(m-n)+n;   // 随机行
        char** table = malloc(row*sizeof(char*));
        for(int i=0;i<row;++i){
                int col = rand()%(m-n)+n;    //随机列
                table[i] = calloc(col+1,sizeof(char));   // 记得\0
                for(int j=0;j<col;++j){
                        table[i][j] = '*';
                }
        }

        for(int i=0;i<row;++i){
                printf("%s\n",table[i]);
        }

        for(int i=0;i<row;++i){
                free(table[i]);
                table[i] = NULL;
        }
        free(table);
        table = NULL;
}

结果为:

2 8
******
*******
**
****

你可能感兴趣的:(C语言,c语言)