C语言-对malloc的使用与理解

一、malloc函数分析

  1.函数原型

    void  * malloc(size_t  size);

  2.Function(功能)

    Allocates a block of size bytes of memory, returning a pointer to the beginning of the block

    译:在内存中分配 size 个字节的空间,返回一个指向”内存空间开头“的指针(指针类型为void *)。

  3.Parameters

    size

      size of  the memory block,in bytes

  4.Return Value

    On success, a pointer to the memory block allocated by the function.
    The type
of this pointer is always void*, which can be cast to the desired type
of data pointer in order to be dereferenceable.
    If the function failed to
allocate the requested block of memory, a null pointer is returned.

    译:申请内存成功,返回一个指向”被函数分配的内存空间“的指针。

      这个指针的类型是void *(指向任意类型的指针),它可以被转换为期望类型的数据指针,以便能够解除引用。

      如果函数分配被要求的内存空间失败,则返回一个空指针(NULL

  5.Example   

  

/* malloc example: string generator*/
#include <stdio.h>
#include <stdlib.h>

int main ()
{
  int i,n;
  char * buffer;

  printf ("How long do you want the string? ");
  scanf ("%d", &i);

  buffer = (char*) malloc (i+1);
  if (buffer==NULL) exit (1);

  for (n=0; n<i; n++)
    buffer[n]=rand()%26+‘a‘;
  buffer[i]=‘\0‘;

  printf ("Random string: %s\n",buffer);
  free (buffer);

  return 0;
}

  6. 注:

      1.在#include<stdlib.h>中被定义。

      2.malloc是从堆(heap)中分配内存空间,而不是栈(stack)。

      3.内存有可能分配失败,所以需要使用下面的检测程序来检测内存是否分配失败。

      if(t_array == NULL)
      {
          printf(Failde to allocate memory block! \n);        exit(1);  //结束程序
      } 

      4.内存不再使用时,应使用free()函数将内存块释放

      5.malloc 函数返回的是 void * 类型,如果你写成:p = malloc (sizeof(int)); 则程序无法通过编译,报错:“不能将 void* 赋值给 int * 类型变量”。

                   所以必须通过 (int *) 来将强制转换

      6.函数的实参为 sizeof(int) ,用于指明一个整型数据需要的大小。如果你写成:    

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

        也能通过编译,但事实上只分配了1个字节大小的内存空间,当你往里头存入一个整数,就会有3个字节无家可归,而直接“住进邻居家”!

       造成的结果是后面的内存中原有数据内容全部被清空。

      7.malloc 只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存中,其值将是随机的。

二、使用malloc申请动态内存空间的两种情况:

  1. 大容量内存需求

    一般需要的内存空间超过0.5M的时候时,要使用malloc来申请内存空间。可以这样理解,因为内存过大,不好管理内存,此时就需要用malloc来管理,而不是IDE。

  2.不确定内存需求

    当我们需要的内存空间不确定大小的情况下,为了不浪费内存空间,就要用到malloc函数。可以这样理解,如果说静态的内存空间是一个铁盒子的话,那动态内存空间就是一个可收缩的袋子,它的容量可以根据你所装物体的体积不同而改变。而使用静态内存,要么就是申请的内存空间过大,造成浪费,要么就是申请的内存空间不够用,程序异常报错。

  

三、如何正确使用malloc函数进行动态分配

  1.申请一维数组

    一维数组的数组名可以看成数组起始元素的首地址,因此我定义一个int *t_array的指针,分配n个大小的int型空间,写法如下:

      int * t_array;  //定义一维整型指针数组

      t_array = (int *)malloc( sizeof(int) * n );  //分配4*n个字节的内存空间

      if(t_array == NULL)

      {

         printf("Failed to allocate memory block! \n");

         exit(1);

      }

      //具体代码

      free(t_array);  //内存空间不再用时,释放内存空间

  

  2.申请二维空间

    二维数组的数组名是其所有一维数组的首地址,因为二维数组的数组名是指针的指针,因为我定义一个row行column列的二维数组,写法如下:

      int ** t_array;  //定义二维整型指针数组

      int row;  //行序号

      int column; //列序号

      int i;

      scanf("%d %d", row,column);  //输入行数,列数

      t_array = (int **)malloc( sizeof(int *) * row);  //分配所有行的首地址 (分配的是行指针单元,每个单元的大小为 sizeof(int *) )

      for(i=0;i<row;i++)

        t_array[i] = (int *)malloc(sizeof(int) * column );  //再分配column个整数单元,上面的row个行指针指向这column个整数单元首地址       

       //具体代码

      

        if(t_array == NULL)  //检验是否成功分配内存
       {
        printf("Failed to allocate memory block! \n");
        exit(1);
       }

       for(i=0;i<row;i++)  //检验是否成功分配内存
       {
        if(t_array[i] == NULL)
        {
          printf("Failed to allocate memory block! \n");
          exit(1);
        }
       }

      for(i=0;i<row;i++)
        free(t_array[i]);      free(t_array)

  总结:malloc()函数其实就在内存中找一片指定大小的空间,然后将这个空间的首地址范围给一个指针变量,这里的指针变量可以是一个单独的指针,也可以是一个数组的首地址,这要看malloc()函数中参数size的具体内容。我们这里malloc分配的内存空间在逻辑上连续的,而在物理上可以连续也可以不连续。对于我们程序员来说,我们关注的是逻辑上的连续,因为操作系统会帮我们安排内存分配,所以我们使用起来就可以当做是连续的。

时间: 2024-10-11 07:20:08

C语言-对malloc的使用与理解的相关文章

论C语言的malloc,calloc,new,realloc,alloca的机制和区别

最近笔试老是遇到关于C语言的malloc,new之类的内存机制问题,作为一个做java开发的程序员不免有些郁闷,驾驭不了.乘空闲下来的这些时间,好好整理下C语言中各个内存函数的简单机制,作用和区别: C语言内存分配方式 (1) 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. (2) 在栈上创建.在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放.栈内存分配运算内置于处理器的指令集

理解C#语言中的类型转换----初学者的理解,请大神指教

一下都是在视频教学中学到后的理解,如果说错了请大神指教 C#语言中的类型转换,就是将某个数据要转换成另一个类型的数据. c#语言中的数据类型主要有: char类型(字符类型): string类型(字符串类型): int类型(整数类型): double类型(小数类型): 类型转换主要分为三种: 1:任意类型转换为string类型: 转换代码书写格式为:待转换的数据.Tostring(): a,这里的待转换的数据指的是需要转换的数据或变量.后面的Tostring():是固定书写. 转换完成后的返回类

[转]PHP语言的数据库操作函数的理解

就我接触到的R语言以及对数据库的操作来说,基本的操作其实也就是CRUD(Create, Read, Update, Delete). 习惯了之后,对PHP中的MYSQLI操作函数感觉很不适应,查询或者执行总是有非常多的实现方法,有些莫名其妙. 以下是对一些常用操作的学习汇总: mysqli预处理编译的深入理解

sql 语言---对六个部分的理解

结构化查询语言(Structured Query Language)简称SQL 是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询.更新和管理关系数据库系统 SQL语言提出  :1974年由Boyce和Chamberlin 主要分为:数据定义.数据操纵和数据控制 优点: 结构化查询语言是高级的非过程化编程语言, 允许用户在高层数据结构上工作. 不要求用户指定对数据的存放方法,了解具体的数据存放方式, 具有完全不同底层结构的不同数据库系统可以使用相同的结构化查询语言作为

智能合约语言 Solidity 教程系列10 - 完全理解函数修改器

这是Solidity教程系列文章第10篇,带大家完全理解Solidity的函数修改器.Solidity系列完整的文章列表请查看分类-Solidity. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还不了解,建议你先看以太坊是什么 函数修改器(Function Modifiers) 函数修改器(Modifiers)可以用来改变一个函数的行为.比如用于在函数执行前检查某种前置条件. 如果熟悉Python的同学,会发现函数修改器的作用和Py

c语言中对字段宽度的理解?

1 /************************************************************************* 2 > File Name: printf.c 3 > Author: Mr.Yang 4 > Purpose:演示printf的用法 5 > Created Time: 2017年05月21日 星期日 10时07分44秒 6 ****************************************************

黑马程序员--C语言中结构体-我之理解

------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------- 什么是结构体? “结构”是一种构造类型,它是由若干“成员”组成的.每一个成员可以是一个基本数据类型或者又是一个构造类型. 为什么要有结构类型? 结构体可以把功能相同的数据组织起来,存在一起,用的时候方便,而且在调用函数时,若 传递参数较多

java语言的特性及应用

java语言定义: Java是一种可以撰写跨平台应用程序的面向对象的程序设计语言. Java 技术具有卓越的通用性.高效性.平台移植性和安全性,广泛应用于PC.数据中心.游戏控制台.科学超级计算机.移动电话和互联网,同时拥有全球最大的开发者专业社群. 组成: Java由四方面组成:●Java编程语言,即语法.●Java文件格式,即各种文件夹.文件的后缀.●Java虚拟机(JVM),即处理*.class文件的解释器.●Java应用程序接口(Java API). Java分为三个体系,分别为Java

【转】《深入理解计算机系统》C程序中常见的内存操作有关的典型编程错误

原文地址:http://blog.csdn.net/slvher/article/details/9150597 对C/C++程序员来说,内存管理是个不小的挑战,绝对值得慎之又慎,否则让由上万行代码构成的模块跑起来后才出现内存崩溃,是很让人痛苦的.因为崩溃的位置在时间和空间上,通常是在距真正的错误源一段距离之后才表现出来.前几天线上模块因堆内存写越界1个字节引起各种诡异崩溃,定位问题过程中的折腾仍历历在目,今天读到<深入理解计算机系统>第9章-虚拟存储器,发现书中总结了C程序中常见的内存操作有