目录
- 一、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是用于类型重定义
二、虚拟内存
(一)虚拟内存分布
- 内核空间:(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指向第二次申请的内存空间,没有指针指向第一次申请的内存空间。