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

相关文章

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

C语言中自动与强制转换全解析

《C语言中自动与强制转换全解析》在编写C程序时,类型转换是确保数据正确性和一致性的关键环节,无论是隐式转换还是显式转换,都各有特点和应用场景,本文将详细探讨C语言中的类型转换机制,帮助您更好地理解并在... 目录类型转换的重要性自动类型转换(隐式转换)强制类型转换(显式转换)常见错误与注意事项总结与建议类型

Go语言利用泛型封装常见的Map操作

《Go语言利用泛型封装常见的Map操作》Go语言在1.18版本中引入了泛型,这是Go语言发展的一个重要里程碑,它极大地增强了语言的表达能力和灵活性,本文将通过泛型实现封装常见的Map操作,感... 目录什么是泛型泛型解决了什么问题Go泛型基于泛型的常见Map操作代码合集总结什么是泛型泛型是一种编程范式,允

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

C语言小项目实战之通讯录功能

《C语言小项目实战之通讯录功能》:本文主要介绍如何设计和实现一个简单的通讯录管理系统,包括联系人信息的存储、增加、删除、查找、修改和排序等功能,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录功能介绍:添加联系人模块显示联系人模块删除联系人模块查找联系人模块修改联系人模块排序联系人模块源代码如下

基于Go语言实现一个压测工具

《基于Go语言实现一个压测工具》这篇文章主要为大家详细介绍了基于Go语言实现一个简单的压测工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录整体架构通用数据处理模块Http请求响应数据处理Curl参数解析处理客户端模块Http客户端处理Grpc客户端处理Websocket客户端

使用SQL语言查询多个Excel表格的操作方法

《使用SQL语言查询多个Excel表格的操作方法》本文介绍了如何使用SQL语言查询多个Excel表格,通过将所有Excel表格放入一个.xlsx文件中,并使用pandas和pandasql库进行读取和... 目录如何用SQL语言查询多个Excel表格如何使用sql查询excel内容1. 简介2. 实现思路3

Go语言实现将中文转化为拼音功能

《Go语言实现将中文转化为拼音功能》这篇文章主要为大家详细介绍了Go语言中如何实现将中文转化为拼音功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 有这么一个需求:新用户入职 创建一系列账号比较麻烦,打算通过接口传入姓名进行初始化。想把姓名转化成拼音。因为有些账号即需要中文也需要英