C语言学习(八)typedef 虚拟内存 malloc/free

2024-05-12 13:36

本文主要是介绍C语言学习(八)typedef 虚拟内存 malloc/free,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 一、typedef 类型重定义
    • (一)使用
    • (二)define和typedef的区别
      • 1. 编译处理的阶段不同
      • 2. 功能不同
  • 二、虚拟内存
    • (一)虚拟内存分布
    • (二)内存分布
      • 1. 静态分配
      • 2. 动态分配
  • 三、malloc/free函数
    • (一) malloc函数
        • (1)定义
        • (2)使用
    • (二) free函数
    • (三) 使用
  • 四、内存泄漏
    • (一)概念
    • (二) 规避方法
    • (三)示例

一、typedef 类型重定义

(一)使用

typedef <数据类型> <标识符>

typedef int int32_t; typedef int arr_t[2][3];//两行三列的二维数组类型typedef int(*fun_t)(int,int); //定义int(*)(int,int)类型

(二)define和typedef的区别

1. 编译处理的阶段不同

define在预处理阶段,typedef参与编译阶段

  • 注:编译的过程:
  • 预处理:展开头文件,删除注释,宏替换
    gcc - E hello.c -o hello.i
    hello.i 就是预处理文件。预处理不会检查语法错误。
  • 编译:语法统计,词法统计,语义分析
    gcc -S hello.i -o hello.s
    生成一个汇编文件。编译会检查语法错误
  • 汇编
    gcc -c hello.s -o hello.o
    生成一个二进制文件。
  • 链接:链接库文件,生成一个可执行的二进制文件
    gcc hello.o -o hello

2. 功能不同

define是字符串原样替换;typedef是用于类型重定义

二、虚拟内存

(一)虚拟内存分布

图片1

  • 内核空间:(0xcccc cccc~0xffff ffff)程序共用,不允许用户使用
  • 栈区:空间自动申请,自动释放;向下生长
    主要存放局部变量,未初始化时是乱值。
    (栈区空间,windows是2M,可以调至10M;在Linux中是8M)
  • 堆区:手动申请,手动释放;向上生长
    malloc / realloc / calloc
    (堆区空间,大概1.9G)
  • 常量区
    .bss段:未初始化的全局变量
    .data段 :初始化的全局变量
    .readonly段:只读段
    .text段 (代码区):程序代码

mmu固件:将虚拟内存映射到物理内存中。

eg:分析以下数据存放在内存中的位置:number1 , number2, number3, number4, p1, p2 ,p3 *p1,*p3, function, *p2

include <stdio.h>int number1;  
未初始化的全局变量:常量区-->.bss段
int number2 = 10;   
初始化的全局变量:常量区-->.data段
字面量值10存储在常量区。int function() 代码:常量区-->代码区
{int number3 = 30;  初始化的局部变量:栈区int number4;  未初始化的局部变量:栈区
}
int main() 代码:常量区-->代码区
{char * p1 = "hello world";  p1 局部变量:栈区*p1:常量区-->readonly段char p2[]= "abc"  p2 局部变量:栈区*p2:栈区char *p3 = (char *)malloc(20);   p3 局部变量:栈区; p3指向的内存空间 堆区free(p3);p3 = NULL;
}
  • 注:当程序加载到内存中时,number2的内存空间(在.data段)会被分配,
    并且其值会被初始化为10(这个值来源于常量区,但在运行时它是存储在.data段中的)。

(二)内存分布

C语言分配内存的方法:静态分配 动态分配

1. 静态分配

在编译节点的时候,已经确定了分配空间大小。
eg:int a=10; intarr[2][2];

2. 动态分配

编写程序时,不确定要申请多少空间,在执行时根据需要进行的空间分配。
eg:malloc分配的空间就属于动态分配。

三、malloc/free函数

(一) malloc函数

(1)定义
头文件(标准库文件):
#include <stdlib.h>函数原型:
void *malloc(size_t size);函数功能:在内存中(堆)区中开辟指定大小的地址连续的空间。函数参数:size_t  无符号整型,size表示开辟多少字节空间。函数返回值:成功,返回开辟空间的首地址;失败,返回一个NULL
(2)使用

申请空间为一段连续的空间:
① 可以使用下标进行访问
②可以通过指针进行访问

(二) free函数

头文件(标准库文件):
#include <stdlib.h>函数原型:
void free(void *ptr);函数功能:释放手动申请的空间。函数参数:void* ptr: malloc/realloc/calloc申请的空间的首地址
  • 注:释放已经释放过的指针会造成程序错误。
  • 但是指针指向NULL时,释放多次都不会报错。

(三) 使用

#include <stdio.h>
#include <stdlib.h>int main()
{//申请空间int *p =mymalloc(20);if(!p){printf("create fail!\n");return -1;}//向空间内写值*p = 10;*(++p)= 20;//读值for (int i=0;i<20;i++){printf("%d ",*(p+i));}//释放空间free(p);p = NULL;/*释放完空间后,将指针指向NULL/指向NULL后,再次释放不会报错*/
}int mymalloc(int size)
{int *p = (int *)malloc(size);if(!p){printf("fail!\n");return -1;}else{prnintf("sucess:%p\n",p);}return 0;
}

eg
功能需求
定义一个函数: create 功能: 在内存中申请n个字节大小. n是一个参数.
这个函数的返回值是指针类型.
set(指针)函数 功能: 从键盘中输入n个值, 将N个值存入 create创建的空间中.
sort函数():使用冒泡排序对这n个值进行排序.
max函数(): 返回空间中的最大值
min函数(): 返回空间中的最小值.、

代码实现

#include <stdio.h>
#include <stdlib.h>int min(int *arr,int len);
int max(int *arr,int len);
void sort(int *arr,int len);
void set(int *a,int n);
int* create(int size);
void show(int *arr,int size);
void create_noReturn(int **p,int size);//使用二级指针传参int main()
{int size;//申请空间printf("please input size:");scanf("%d",&size);/*** * int *p = NULL;* create_noReturn(&p,size);***/int *p = create(size);//20个字节,5个int//判断p空间是否申请成功if(p!){printf("create fail!!");return -1;}//向空间内写值set(p,size);//排序,读值sort(p,size);show(p,size);printf("MAX:%d\n",max(p,size));printf("MIN:%d\n",min(p,size));//释放空间free(p);p = NULL;
}
void show(int *p,int size)
{for(int i=0;i<5;i++){printf("%d ",*(p+i));}putchar(10);
}
//申请n字节大小,返回值是申请空间的指针
int* create(int size)
{int *p = (int *)malloc(4*size);if(!p){printf("fail!\n");return NULL;}return p;
}
//无返回值的空间分配
void create_noReturn(int **p,int size)
{int s=4*size;*p =(int*)malloc(s);}   void set(int *a,int n)
{for(int i=0;i<n;i++){printf("please input %d num:",i+1);scanf("%d",a+i);                                                                                                                                                                                                                                                                                                       }
}//排序
void sort(int *arr,int len)
{int flag = 0;for(int i=0;i<len-1;i++){flag = 0;for(int j=0;j<len-i-1;j++){if(*(arr+j)>*(arr+j+1)){int temp=*(arr+j);*(arr+j)=*(arr+j+1);*(arr+j+1)=temp;flag=1;}}if(!flag) break;}
}//最大值
int max(int *arr,int len)
{int max = *arr;for(int i=0;i<len;i++){if(max<(*(arr+i)))max = *(arr+i);}return max;
}//最小值
int min(int *arr,int len)
{int min = *arr;for(int i=0;i<len;i++){if(min>(*(arr+i)))min = *(arr+i);}return min;
}

四、内存泄漏

(一)概念

在C语言中调用malloc/calloc/realloc函数时,申请内存后没有调用free函数进行释放内存,导致内存越用越少。

(二) 规避方法

当空间使用完毕后,及时释放内存。

(三)示例

int main()
{int * p =malloc(20);p = malloc(20);free(p);return 0;
}

此时p指向第二次申请的内存空间,没有指针指向第一次申请的内存空间。

这篇关于C语言学习(八)typedef 虚拟内存 malloc/free的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/982775

相关文章

C语言线程池的常见实现方式详解

《C语言线程池的常见实现方式详解》本文介绍了如何使用C语言实现一个基本的线程池,线程池的实现包括工作线程、任务队列、任务调度、线程池的初始化、任务添加、销毁等步骤,感兴趣的朋友跟随小编一起看看吧... 目录1. 线程池的基本结构2. 线程池的实现步骤3. 线程池的核心数据结构4. 线程池的详细实现4.1 初

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学