c语言 第八章:内存管理、位运算
·
1. 操作系统内存管理
①内存分布
②堆和栈的区别
栈区:
1. 栈区用来保存局部变量、函数的形参返回值、及函数调用时的保护现场;
2. 栈区由操作系统自动管理;
3. 栈区默认大小为8M, 比堆区空间小;
4. 栈的访问效率要比堆的访问效率高;
堆区:
1. 堆区由开发人员手动申请和释放,使用完时及时释放,否则造成内存泄露。
2. 堆区空间比栈空间大,访问效率相对较低。
③堆区空间使用场景
在函数中开辟的空间,希望随着函数结束,该空间任然存在,可以去堆上开辟。
当需要的空间比较大时,可以去堆上开辟,栈区空间有限,默认8M。
堆区空间使用(动态内存分配):
void *malloc(size_t size);
功能:向堆区申请内存空间
参数:
size:申请的空间字节数
返回值:
成功:返回申请到的空间首地址
失败:NULL
void free(void *ptr);
功能:释放申请的堆区空间
参数:
ptr:申请到的堆区的空间首地址。
void *calloc(size_t nmemb, size_t 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;
}
for (int i = 0; i < ARRAY_LEN; ++i)
{
printf("%d ", pa[i]);
}
printf("\n");
2. 位运算
①位运算基础
& 按位与 全1为1,有0则0
| 按位或 有1则1,全0为0
^ 按位异或 相同为0,相异为1
~ 按位取反 1取反为0,0取反为1
<< 按位左移 按位左移,低位补0 num << n <===> num * 2^n
>> 按位右移 按位右移动,有符号数高位补符号位;无符号数高位补0
num >> n <===> num / 2^n
9 & 6
0000 0000 0000 0000 0000 0000 0000 1001 &
0000 0000 0000 0000 0000 0000 0000 0110
0000 0000 0000 0000 0000 0000 0000 0000
9 | 6
0000 0000 0000 0000 0000 0000 0000 1001 |
0000 0000 0000 0000 0000 0000 0000 0110
0000 0000 0000 0000 0000 0000 0000 1111
9 ^ 6
0000 0000 0000 0000 0000 0000 0000 1001 ^
0000 0000 0000 0000 0000 0000 0000 0110
0000 0000 0000 0000 0000 0000 0000 1111
~9
~0000 0000 0000 0000 0000 0000 0000 1001
1111 1111 1111 1111 1111 1111 1111 0110
9 << 3
0000 0000 0000 0000 0000 0000 0000 1001 << 3
0000 0000 0000 0000 0000 0000 0100 1000
9 >> 3
0000 0000 0000 0000 0000 0000 0000 1001 >> 3
0000 0000 0000 0000 0000 0000 0000 0001
②位运算的使用
a.指定n位置1
0000 0000--》0000 1000
0000 0001 << 3
0000 1000
1010 0000 |
0000 1000
1010 1000
num = num | 1 << n;
1010 0001 | 0000 0001 << 6
0100 0000
1110 0001
b. 指定第n位清0
1010 1010 & ~(1 << 3)
1111 0111
1010 0010
1111 0111 <==> ~0000 1000 <==> ~(1 << 3)
num = num & ~(1 << n);
0011 1100 1010 1010 & ~(1 << 10) & ~(1 << 11)
1111 1011 1111 1111
0011 1000 1010 1010
1111 0111 1111 1111
0011 0000 1010 1010
0000 0100 0000 0000
1111 1011 1111 1111
c. 两数交换(不使用中间变量)
方法一(位运算,无中间变量):
a = a ^ b;
b = a ^ b;
a = a ^ b;
====》
a ^ a == 0
a ^ 0 == a
b = (a ^ b) ^ b = a ^ b ^ b = a ^ (b ^ b) = a ^ 0 = a;
a = a ^ b = a ^ b ^ a = 0 ^ b = b;
方法二(有中间变量):
int tmp = 0;
tmp = a;
a = b;
b = tmp;
方法三(求和方式,无中间变量):
a = a + b;
b = a - b; ===>a + b -b = a
a = a - b; ===>a + b - b = a + b - a
=>位运算符的优先级:
~ 大于 << >> 大于 & 大于 ^ 大于 |
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)