精华内容
下载资源
问答
  • C语言动态内存分配

    2019-12-06 15:34:25
    只是为了方便回顾 C语言动态内存分配

    只是为了方便回顾
    C语言动态内存分配

    展开全文
  • c语言动态内存分配

    2020-12-27 17:34:39
    c语言动态内存分配 静态内存分配: 在进程的地址空间中,代码区、常量区、全局数据区的内存在程序启动时就已经分配好了,它们大小固定,不能由程序员分配和释放,只能等到程序运行结束由操作系统回收。 动态内存分配...

    c语言动态内存分配

    静态内存分配: 在进程的地址空间中,代码区、常量区、全局数据区的内存在程序启动时就已经分配好了,它们大小固定,不能由程序员分配和释放,只能等到程序运行结束由操作系统回收。
    动态内存分配: 栈区和堆区的内存在程序运行期间可以根据实际需求来分配和释放,不用在程序刚启动时就备足所有内存。

    动态内存的优点:可以让程序对内存的管理更加灵活和高效,需要内存就立即分配,而且需要多少就分配多少,从几个字节到几个GB不等;不需要时就立即回收,再分配给其他程序使用。

    动态内存分配函数

    在堆上分配和释放内存需要用到C语言标准库中的几个函数:malloc()、calloc()、realloc() 和 free()。

    1. malloc()

    原型:void* malloc (size_t size);

    作用:在堆区分配 size 字节的内存空间。

    返回值:成功返回分配的内存地址,失败则返回NULL。

    注意:

    • 函数的返回值类型是 void ,void 并不是说没有返回值或者返回空指针,而是返回的指针类型未知。所以在使用 malloc() 时通常需要进行强制类型转换,将 void 指针转换成我们希望的类型。
    • 分配内存在动态存储区(堆区),手动分配,手动释放。
    • 申请时空间可能有也可能没有,需要自行判断。
    1. calloc()

    原型:void* calloc(size_t n, size_t size);

    功能:在堆区分配 n*size 字节的连续空间。

    返回值:成功返回分配的内存地址,失败则返回NULL。

    注意:

    • calloc() 在内存中动态地分配 num 个长度为 size 的连续空间,并将每一个字节都初始化为 0。
    • calloc() 与 malloc() 的一个重要区别是:calloc() 在动态分配完内存后,自动初始化该内存空间为零,而 malloc() 不初始化,里边数据是未知的垃圾数据。
    1. realloc()

    原型:void* realloc(void *ptr, size_t size);

    功能:对 ptr 指向的内存重新分配 size 大小的空间。

    返回值:成功返回更改后的内存地址,失败则返回NULL。

    1. free()

    原型:void free(void* ptr);

    功能:释放由 malloc()、calloc()、realloc() 申请的内存空间。

    几点注意

    • 每个内存分配函数必须有相应的 free 函数,释放后不能再次使用被释放的内存。

    • free ( ) 并不能改变指针的值,指针依然指向以前的内存,为了防止再次使用该内存,建议将指针的值手动置为 NULL。

    • sizeof 是一个单目操作符,不是函数,用以获取数据类型的长度时必须加括号,例如 sizeof(int)、sizeof(char) 等。

    最后是一个综合的示例:

    #include <stdio.h>
    #include <stdlib.h>
    
    #define  N  (5)
    #define  N1 (7)
    #define  N2 (3)
    
    int main()
    {
        int *ip;
        int *large_ip;
        int *small_ip;
        if((ip = (int*)malloc(N * sizeof(int))) == NULL) 
        {
            printf("memory allocated failed!\n");
            exit(1);
        }
        int i;
        for(i = 0; i < N; i++)
        {
            ip[i] = i;
            printf("ip[%d] = %d\t", i, ip[i]);
        }
        printf("\n");
    
        if((large_ip = (int* )realloc(ip, N1 * sizeof(int))) == NULL)
        {
            printf("memory allocated failed!\n");
            exit(1);
        }
        for(i = N; i < N1; i++)
            large_ip[i] = 9;
        for(i = 0; i < N1; i++)
            printf("large_ip[%d] = %d\t", i, large_ip[i]);
        printf("\n");
    
        if((small_ip = (int*)realloc(large_ip, N2 * sizeof(int))) == NULL)
        {
            printf("memory allocated failed!\n");
            exit(1);
        }
        for(i = 0; i < N2; i++)
            printf("small_ip[%d] = %d\t", i, small_ip[i]);
        printf("\n");
    
        free(small_ip);
        small_ip = NULL;
    
        system("pause");
        return 0;
    }
    
    展开全文
  • C语言 动态内存分配

    2017-04-05 16:34:33
    C语言 动态内存分配参考:Sizeof与Strlen的区别与联系:http://blog.csdn.net/u012005313/article/details/46790921 C/C++ memset的作用以及memcpy和strcpy的区别:...

    C语言 动态内存分配

    参考:

    Sizeof与Strlen的区别与联系http://blog.csdn.net/u012005313/article/details/46790921
    C/C++ memset的作用以及memcpy和strcpy的区别http://blog.csdn.net/u012005313/article/details/48005689
    Linux C语言应用 - main函数解析,时间函数,C语言代码的分配机制(malloc,calloc,realloc,free)http://blog.csdn.net/u012005313/article/details/50704866


    关于如何在 C 语言中进行动态内存分配,之前也有过一些总结,不过并没有深入。在查找的过程中,发现很多知识忘记了,所以记录下这篇关于 C 语言中如何进行动态内存分配


    主要内容:

    1. sizeofstrlen
    2. free
    3. memset
    4. malloccallocrealloc

    sizeofstrlen

    在分配内存之前,需要了解给指针分配多少个字节的内存块,使用函数 sizeof 和 strlen

    sizeof

    百度百科:sizeof

    sizeofC/C++ 中的一个操作符,其作用是返回一个对象或类型所占的内存字节数

    其返回值类型为 size_t,通常是 unsigned int

    当参数为指针时,其返回值为存储该指针所占的空间大小(即存储该指针的地址的长度)
    当参数为数组时,其返回值为分配的数组空间大小

    程序如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(int argc, char* argv[]) {
    
        char arr[200] = "Hello World";
        printf("sizeof(arr): %d\n", sizeof(arr));
        printf("arr: %s\n", arr);
    
        char *brr = "Hello World";
        printf("sizeof(brr): %d\n", sizeof(brr));
        printf("brr: %s\n", brr);
    
        char *crr = NULL;
        printf("sizeof(crr): %d\n", sizeof(crr));
        printf("crr: %s\n", crr);
    
        crr = (char*)malloc(sizeof(arr));
        strcpy(crr, arr);
        printf("sizeof(crr): %d\n", sizeof(crr));
        printf("crr: %s\n", crr);
    
        free(crr);
    
        system("pause");
        return 0;
    }
    

    结果:

    这里写图片描述

    strlen

    百度百科:strlen

    strlen 函数的功能是返回字符串的长度(遇到第一个结束符 \0 为止,但不包括 \0

    其返回值为 size_t,通常为 unsigned int

    程序如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(int argc, char* argv[]) {
    
        char arr[200] = "Hello World";
        printf("sizeof(arr): %d\n", sizeof(arr));
        printf("strlen(arr): %d\n", strlen(arr));
        printf("arr: %s\n", arr);
    
        char *brr = "Hello World";
        printf("sizeof(brr): %d\n", sizeof(brr));
        printf("strlen(brr): %d\n", strlen(brr));
        printf("brr: %s\n", brr);
    
        char *crr = NULL;
        printf("sizeof(crr): %d\n", sizeof(crr));
        //printf("strlen(crr): %d\n", strlen(crr));
        printf("crr: %s\n", crr);
    
        crr = (char*)malloc(sizeof(arr));
        strcpy(crr, arr);
        printf("sizeof(crr): %d\n", sizeof(crr));
        printf("strlen(crr): %d\n", strlen(crr));
        printf("crr: %s\n", crr);
    
        free(crr);
    
        system("pause");
        return 0;
    }
    

    结果:

    这里写图片描述

    利用 sizeofstrlen 进行指针的内存分配

    C 语言中,字符串/字符数组以 \0 结尾;同时输出字符串/字符数组时并不会输出 \0

    所以在动态申请内存时,需要注意申请到 \0 的内存空间

    程序 1 功能:复制单个字符串

    代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(int argc, char* argv[]) {
        char str[30] = "Hello World";
        printf("str: %s\n", str);
    
        char* ptr = NULL;
    
        ptr = (char*)malloc(strlen(str) * sizeof(char) + 1);
    
        strcpy(ptr, str);
    
        printf("ptr: %s\n", ptr);
    
        free(ptr);
    
        system("pause");
        return 0;
    }
    

    结果:

    这里写图片描述

    程序 2 功能:复制多个字符串

    代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(int argc, char* argv[]) {
        char str[30] = "Hello World";
        printf("str: %s\n", str);
    
        char* ptr1 = "1234 asdf 5678";
        printf("ptr1: %s\n", ptr1);
    
        int len = strlen(str) + strlen(ptr1);
    
        char* ptr2 = NULL;
        ptr2 = (char*)malloc(len * sizeof(char) + 1);
        sprintf(ptr2, "%s%s", str, ptr1);
    
        printf("ptr2: %s\n", ptr2);
    
        free(ptr2);
    
        system("pause");
        return 0;
    }
    

    结果:

    这里写图片描述

    note:在进行动态内存分配过程中,先计算出要分配的字符个数,再结合单个字符的长度,同时加上 \0 的长度(加上 1),进行动态内存分配


    free

    百度百科:free

    cstdlib:free

    函数:

    void free (void* ptr);
    

    功能:释放动态申请的内存块

    指针在进行动态内存分配时,是从堆上获取,这意味着申请的内存并不会随着函数的结束而自动释放,会造成内存泄漏,所以需要手动释放内存空间

    常用的动态内存分配函数有 malloccallocrealloc,所以使用上述三种函数获取的内存空间在使用结束后需要手动调用 free 进行释放

    note1:free 完指针后最好手动将指针置为 NULL(如果指针为空,则调用多少次 free 都不会出现问题;但如果不为空,则连续操作两次就会导致程序异常)


    memset

    百度百科:memset

    函数:

    void *memset(void *s, int ch, size_t n);
    
    • 参数 s 为指向的内存首地址;
    • 参数 ch 为要赋值所指定的值;
    • 参数 n 为要操作的字节数

    其返回值为指向 s 的指针

    功能:对内存块进行统一赋值操作,通常用来为新申请的内存进行初始化工作,设为 0 即可,例如:

    memset(s, 0, strlen(s) * sizeof(s))
    

    note:如果申请的内存马上要被覆盖,没必要进行清零操作


    malloccallocrealloc

    malloc

    百度百科:malloc

    函数:

    extern void *malloc(unsigned int num_bytes);
    

    功能:向系统申请分配 num_bytes 个字节的内存空间,该内存空间并未进行初始化

    返回为 void* 类型,可通过类型转换得到需要类型的指针

    代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(int argc, char* argv[]) {
    
        char* ptr = (char*)malloc(sizeof(char) * 30);
        printf("ptr: %s\n", ptr);
    
        memset(ptr, 0, sizeof(char) * 30);
        printf("ptr: %s\n", ptr);
    
        strcpy(ptr, "Hello World");
        printf("ptr: %s\n", ptr);
    
        free(ptr);
    
        system("pause");
        return 0;
    }
    

    结果:

    这里写图片描述

    calloc

    百度百科:calloc

    函数:

    void *calloc(size_t n, size_t size);
    

    功能:申请 n 个长度为 size 字节的连续空间,并自动初始化该内存空间为 0

    callocmalloc 的函数功能相近,只是多了一步初始化清零的操作

    代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(int argc, char* argv[]) {
    
        //char* ptr = (char*)malloc(sizeof(char) * 30);
        char* ptr = (char*)calloc(30, sizeof(char));
        printf("ptr: %s\n", ptr);
    
        //memset(ptr, 0, sizeof(char) * 30);
        //printf("ptr: %s\n", ptr);
    
        strcpy(ptr, "Hello World");
        printf("ptr: %s\n", ptr);
    
        free(ptr);
    
        system("pause");
        return 0;
    }
    

    结果:

    这里写图片描述

    realloc

    百度百科:realloc

    cstdlib:realloc

    函数:

    extern void *realloc(void *mem_address, unsigned int newsize);
    

    功能:

    • 如果指针 mem_address 所知内存空间后面还有足够空间,则扩大 mem_address 所指内存空间;
    • 如果没有足够空间,则新建足够大小空间,将原先数据拷贝到新创建的内存区域(新增加的内存空间没有初始化),并释放原先的内存空间
    • 如果 newsize 小于原先的内存块大小,则有可能会导致数据丢失

    函数运行成功则返回指向被分配内存的指针,否则返回空指针 NULL(返回 NULL时,指针 mem_address 所指内容依旧存在)

    经典案例如下:

    /* realloc example: rememb-o-matic */
    #include <stdio.h>      /* printf, scanf, puts */
    #include <stdlib.h>     /* realloc, free, exit, NULL */
    
    int main()
    {
        int input, n;
        int count = 0;
        int* numbers = NULL;
        int* more_numbers = NULL;
    
        do {
            printf("Enter an integer value (0 to end): ");
            scanf("%d", &input);
            count++;
    
            more_numbers = (int*)realloc(numbers, count * sizeof(int));
    
            if (more_numbers != NULL) {
                numbers = more_numbers;
                numbers[count - 1] = input;
            }
            else {
                free(numbers);
                puts("Error (re)allocating memory");
                exit(1);
            }
        } while (input != 0);
    
        printf("Numbers entered: ");
        for (n = 0; n<count; n++) printf("%d ", numbers[n]);
        free(numbers);
    
        system("pause");
        return 0;
    }
    

    我写了一个例子:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(int argc, char* argv[]) {
    
        char str[200] = "Hello World";
        char str2[200] = "adf 134 adeca adfadec";
    
        char* ptr = NULL;
    
        ptr = (char*)malloc(strlen(str) * sizeof(str) + 1);
        strcpy(ptr, str);
        printf("ptr: %s\n", ptr);
    
        int len = strlen(str) + strlen(str2);
        char* temp = NULL;
        temp = (char*)realloc(ptr, len * sizeof(char) + 1);
        if (temp) {
            ptr = temp;
            strcat(ptr, str2);
            printf("ptr: %s\n", ptr);
        }
    
        free(ptr);
    
        system("pause");
        return 0;
    }
    

    结果:

    这里写图片描述

    note1:函数 realloc 中的参数指针和返回指针不要使用同一个,例如:

    temp = (char*)realloc(temp, 100);
    

    以防内存申请失败,函数返回空时,无法找到原先的内存地址

    展开全文
  • c语言 动态内存分配

    千次阅读 多人点赞 2021-02-25 13:58:48
    动态内存分配数据类型总览内存分配1 整形内存分配2浮点数内存分配 数据类型总览 内存分配 1 整形内存分配 原码: 直接将二进制按照正负数的形式翻译成二进制。其中最高位为符号位 正数为1 负数为0. 反码: 将原码...

    数据类型总览

    在这里插入图片描述

    内存分配

    1 整形内存分配

    1. 原码:
      直接将二进制按照正负数的形式翻译成二进制。其中最高位为符号位 正数为1 负数为0.
    2. 反码:
      将原码的符号位不变,其他位依次按位取反就可以得到了。
    3. 补码:
      反码+1就得到补码。

    在这里插入图片描述
    注意 : 所有的操作都是对补码进行的 因为计算机操作是对内存中的补码进行的
    在这里插入图片描述

    2浮点数内存分配

    先看这个例子
    在这里插入图片描述
    本例可以看出 整形的9 用浮点数的读取方式 他的数值就出现了 天翻地覆的变化 同样 浮点数的9用整形的方式读取也出现了类似的情况。
    由此可见 浮点数的存储方式和整形的存储方式是不一样的。
    根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:

    1. (-1)^S * M * 2^E
    2. (-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数。
    3. M表示有效数字,大于等于1,小于2
    4. 2^E表示指数位

    存储模型示意图
    举例来说: 十进制的5.0,写成二进制是 101.0 ,相当于 1.01×2^2 。 那么,按照上面V的格式,可以得出s=0,
    M=1.01,E=2。
    十进制的-5.0,写成二进制是 -101.0 ,相当于 -1.01×2^2 。那么,s=1,M=1.01,E=2。
    注意!!!!

    1. 这里的^ 表示多少次方
    2. 不可与十进制混淆 这里的1.01为二进制数 每乘以2小数点往后靠一位
    3. 在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分
      比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。
      以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字
      E的特殊情况讨论
      首先,E为一个无符号整数(unsigned int) 这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的取值范围为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真
      实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如,2^10的E
      是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。
      指数E从内存中取出还可以再分成三种情况:
    4. E不全为0或不全为1
      这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前
      加上第一位的1。 比如: 0.5(1/2)的二进制形式为0.1,由于规定正数部分必须为1,即将小数点右移1位,
      则为1.0*2^(-1),其阶码为-1+127=126,表示为01111110,而尾数1.0去掉整数部分为0,补齐0到23位
      00000000000000000000000,则其二进制表示形式为:
    5. E全为0
      这时,浮点数的指数E等于1-127(或者1-1023)即为真实值, 有效数字M不再加上第一位的1,而是还原为
      0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。
    6. E全为1
      这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);
      现在我们在回过头看例题
      首先我们先得出9的
      在这里插入图片描述
      同理可以得出
      在这里插入图片描述

    3字符型内存分配

    字符型存放的是字符对应的ascII码表的值
    在这里插入图片描述

    大小端的判断

    定义

    1. 大端存储:就是把一个数的低位字节序的内容存放到高地址处,高位字节序的内容存放在低地址处。

    2. 小端存储:就是把一个数的低位字节序的内容存放到低地址处,高位字节序的内容存放在高地址处。
      高位 低位
      在这里插入图片描述

    我们观察 得知
    在这里插入图片描述
    我们的vs2019 存储为小端存储
    如何设计代码区分 存储方式呢

    #define _CRT_SECURE_NO_WARNINGS
    
    #include<stdio.h>
    int Differentiate(i)
    {
    	
    	 return *(char*)&i;
    }
    
    int main()
    {
    	int a = 0x01;
    	int m = Differentiate(a);
    	if (m == 1)
    	{
    		printf("小端");
    	}
    	else
    		printf("大端");
    	return 0;
    }
    
    展开全文
  • 我们又见面啦,上一期的C语言构造哈夫曼树-哈夫曼编码相信大家已经好好复习啦,今天我们要学习的新内容是C语言动态内存分配函数在C中我们开辟内存空间有两种方式:1.静态开辟内存:例如:这种开辟内存空间的特点是所开辟...
  • 主要介绍了C语言 动态内存分配详解的相关资料,需要的朋友可以参考下

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,807
精华内容 1,922
关键字:

c语言动态内存分配

c语言 订阅