内存管理、位运算

1.操作系统内存管理

内存分区(4G虚拟地址空间)

分区 说明
内核空间 操作系统内核使用,应用程序不能直接访问
栈区 保存局部变量、函数形参、返回值、函数调用保护现场;操作系统自动管理;默认大小8M,空间小,访问效率高,函数执行结束自动回收空间
堆区 开发者手动申请、手动释放;空间大,访问效率低于栈;如果申请后不释放会产生内存泄漏
数据区 .data段:存放已初始化全局变量、static静态变量
.bss段:存放未初始化全局变量、static静态变量,系统自动默认清0
字符常量区:存放字符串常量,只读
文本区 存放程序代码指令,只读

堆区与栈区对比

  1. 栈区:系统自动分配回收;空间小(默认8M);效率高;函数结束自动释放;不能手动控制生命周期。
  2. 堆区:程序员手动malloc/calloc申请、free释放;空间大;效率略低;函数结束不会自动释放,忘记释放造成内存泄漏。

堆区动态内存分配函数

头文件:#include <stdlib.h>

  1. malloc
void *malloc(size_t size);
  • 功能:向堆内存申请size字节大小的空间
  • 参数:size 需要申请的字节数
  • 返回值:成功返回堆空间首地址;申请失败返回NULL

⚠️申请完必须判断返回值是否为NULL,防止空指针访问。

  1. free
void free(void *ptr);
  • 功能:释放堆上申请的内存
  • 参数:malloc/calloc得到的堆空间首地址

注意:不要重复free、不要free栈上变量地址;释放之后建议把指针置NULL,避免野指针。

  1. calloc
void *calloc( size_t nmemb , size_t size );
  • 功能:申请nmemb个元素,每个元素占size字节;申请后内存自动初始化为0
  • 参数:nmemb元素个数;size单个元素字节大小
  • 返回值:成功返回首地址,失败返回NULL

内存泄漏:堆区申请的内存,使用完毕没有调用free释放;程序运行时间越长内存占用越高。

动态数组示例

int *pa = malloc(ARRAY_LEN*sizeof(int));
if (NULL == pa)
{
    printf("malloc error\n");
    return 0;
}
for(int i = 0; i < ARRAY_LEN; i++)
{
    pa[i] = i;
}
free(pa);
pa = NULL;

什么时候使用堆内存:
①函数内开辟的空间,希望函数结束之后内存仍然有效;
②需要开辟很大内存,栈空间不足。

2.位运算

位运算直接操作二进制bit位,运算效率很高;操作数只能是整型(char/short/int/long),浮点不能做位运算。

运算符 名称 运算规则
& 按位与 全1为1,有0则0
` ` 按位或
^ 按位异或 相同为0,相异为1
~ 按位取反 1变0,0变1(单目运算符)
<< 按位左移 整体向左移动n位,低位补0;num << n等价 num∗2nnum * 2^nnum2n
>> 按位右移 整体向右移动n位;有符号数高位补符号位,无符号数高位补0num >> n等价 num/2nnum / 2^nnum/2n

常用位运算场景

  1. 将指定第n位置1:num |= (1 << n);
  2. 将指定第n位清0:num &= ~(1 << n);
  3. 判断第n位是否为1:if(num & (1 << n))
  4. 不使用中间变量交换两个数(异或特性)
a ^= b;
b ^= a;
a ^= b;

补充小知识点

  1. 左移不要移动负数位、不要超过数据本身总bit位数,结果未定义。
  2. 有符号数右移是算术右移,高位补符号;无符号数是逻辑右移,高位补0。
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐