☰
13.高级内存
2026/10/7 16:23:24 网站建设 项目流程

前置知识

1 bit(比特)= 1 个二进制位,只能存 0 / 1 1 byte(字节)= 8 bit

电脑内存是小端存储:数字的低位字节,放在内存低地址。

备注:大部分 x86 电脑是小端;不是所有机器都是小端,考试默认按小端做题。 例:int a = 10; 10 十六进制:00 00 00 0A 内存实际存放顺序:0A 00 00 00,低位字节放前面。

第一章 全部基础整型类型对照表

1.1 有符号类型(可以存正数、负数)

有符号类型,会拿出最高的 1 个 bit 当做符号位 符号位规则:0 = 正数,1 = 负数

表格

类型名格式打印符占用字节取值范围
char%hhd / %c1 字节 (8bit)-128 ~ 127
short%hd2 字节 (16bit)-32768 ~ 32767
int%d4 字节 (32bit)-2147483648 ~ 2147483647
long%ld4 字节 (32bit)-2147483648 ~ 2147483647
long long%lld8 字节 (64bit)-9223372036854775808 ~ 9223372036854775807

重点:long字节数和平台有关;Windows64 位 long 占 4 字节,Linux64 位 long 占 8 字节;long long 固定 8 字节,跨平台不变。 8 位有符号 char 中10000000,在补码规则下定义为 - 128;这个二进制不存在对应的原码与反码。

1.2 无符号类型(只能存≥0 的数字,没有负数)

没有符号位!所有 bit 全部用来存数值,永远代表正数

表格

类型名格式打印符占用字节取值范围
unsigned char%hhu1 字节0 ~ 255
unsigned short%hu2 字节0 ~ 65535
unsigned int%u4 字节0 ~ 4294967295
unsigned long long%llu8 字节0 ~ 18446744073709551615

1.3 浮点数类型(小数)

表格

类型名打印符字节内存拆分 (S+E+M)指数偏移值
float(单精度)%f4 字节1 符号位 + 8 指数位 + 23 尾数位+127
double(双精度)%lf8 字节1 符号位 + 11 指数位 + 52 尾数位+1023

小提示:你直接写 0.5,C 语言默认当成 double;想要 float 小数,写成 0.5f。

第二章 原码、反码、补码(重中之重)

铁律:计算机里面所有整数,永远只保存【补码】!! 电脑减法不会做!减法是转换成「加上负数的补码」,用加法完成运算。

1、原码 把十进制数字,转成二进制,最高位当做符号位 正数:符号位 0,后面写数字二进制 负数:符号位 1,后面写数字二进制

例子,32 位 int: +10 原码:00000000 00000000 00000000 00001010 -10 原码:10000000 00000000 00000000 00001010

2、反码 正数:反码 = 原码(正数三样全部相等) 负数:符号位保持 1 不变,剩下所有 0、1 互相取反

-10 反码:11111111 11111111 11111111 11110101

3、补码(最终存入内存的数!) 正数:补码 = 原码 = 反码 负数:补码 = 反码 + 1 ✅

-10 补码:11111111 11111111 11111111 11110110

验算:10 + (-10) = 0 10 补码 + -10 补码,相加后溢出丢弃,结果为 0,计算正确。

特殊最小值讲解 char -128 char 一共 8 位 bit -128 二进制补码:10000000 它没有原码和反码,是专门规定的特殊值。

第三章 两大类型转换规则

规则 1:大类型 → 小类型(大数据截断,高位扔掉!只留低位字节)

补充:截断完成后,如果是有符号类型,拿到的结果要再按补码规则解析,不要直接当成正数。

例子:int (4 字节) → char (1 字节) 只保留最末尾 1 个字节,前面三个字节直接丢掉!

int a = 123456789; //4字节补码:00000111 01011011 11001101 00010101 char b = a; //截断只取最后 1字节:00010101

例子:int → short(保留最后 2 字节) short → char(保留最后 1 字节)

规则 2:小类型 → 大类型(小转大,空余位置补位,核心!) 有符号变量(char/short/int):符号扩展! 如果小数字最高位是 0(正数)→ 空位全部补 0 如果小数字最高位是 1(负数)→ 空位全部补 1

char a = -123; // char 8位补码:10000101,最高位1代表负数 int b = a; //扩展到32位,前面空位全部补1 //11111111 11111111 11111111 10000101

无符号变量 (unsigned char/short):永远补 0! 不管最高位是啥,空余字节全部填充 0。

unsigned char a = 128; // 8位:10000000 int b = a; //扩展到32位前面全部补0:00000000 00000000 00000000 10000000

第四章 无符号类型经典坑点

坑 1:无符号数永远≥0,i-- 永远不会小于 0!死循环!

unsigned int i; for(i = 9; i >= 0; i--) { printf("%u\n", i); }

当 i=0,再减一:变成无符号最大值 4294967295,永远大于等于 0 → 无限循环! 同理:unsigned char i,i 从 0 再‑1 → 255,循环永远不会结束。

坑 2:strlen 陷阱

备注:strlen 参数是char*,传入负数 char 会发生隐式类型转换,逐个字节查找\0(数值 0)。

char a[1000]; int i; for(i = 0; i < 1000; i++) { a[i] = -1 - i; } printf("%d\n", strlen(a));

char 有 256 个数字循环,从‑1 往下减,经过 256 次一定会遇到数值等于 0,strlen 碰到 0 停止。

第五章 浮点数 float /double 在内存如何存储(IEEE‑754)

小数存储公式:\((-1)^S × M × 2^E\)

S:符号位,0 正数、1 负数 M:尾数,范围固定 [1, 2)

备注:这个1.xxxx前面的 1 叫做隐藏位,存入内存时省略,读取数据的时候自动补上。 E:2 的指数

注意!M 永远是 1.xxxx,前面的数字 1 固定不变! 为了省 1bit 内存,存入电脑的时候,小数点前面的 1 直接丢掉,只存小数点后面数字!

指数 E 可以是负数,电脑不能存负号,于是加上一个偏移值,把负数转正数 float:真实 E + 127 double:真实 E + 1023

实操例子 float a = -10.75f;

步骤 1:十进制小数 → 二进制小数 -10.75 → -1010.11

步骤 2:写成二进制科学计数法 (-1)^1 * 1.01011 * 2^3

步骤 3:拆分 S、真实 E、真实 M S=1,真实 E=3,真实 M=1.01011

步骤 4:转换成电脑存储版本 S 不变:1 存储 E= 3 + 127 = 130,二进制:10000010 存储 M:丢掉小数点前的 1,取 01011,后面补 0 凑满 23 位 → 01011000000000000000000

步骤 5:拼接 1+8+23 1 10000010 01011000000000000000000

第六章 经典例题:同一块内存,两种类型读出完全不一样的值

#include <stdio.h> int main() { int n = 123456789; float* pFloat = (float*)&n; printf("n的值为:%d\n",n); printf("*pFloat的值为:%f\n", * pFloat); *pFloat = -0.75f; printf("n的值为:%d\n",n); printf("*pFloat的值为:%f\n", * pFloat); return 0; }

原理大白话 &n 拿到 n 的内存地址,(float*) 强制转换,并不会修改内存里面 01 二进制!! 只是解读规则变了!

% d:按照【int 整数补码规则】解析这 4 字节二进制 % f:按照【float 浮点数 S‑E‑M 规则】解析一模一样的 4 字节二进制 同一堆 0 和 1,两套解读方案 → 打印出完全不同的数字!

⚠重点区分:(float*)&n是指针类型强制转换,不改内存二进制,只是换解析规则;float(n)是数值转换,会重新计算二进制,二者完全不一样!

第七章 指针基础入门

指针变量用来存放字节的地址

32 位 (X86) 电脑:地址 32 位二进制 → 指针占 4 字节 64 位 (X64) 电脑:地址 64 位二进制 → 指针占 8 字节

& 和 * & 变量名:取出变量第一个字节的地址

  • 有两层身份:
  1. 定义变量时:int *p;,代表 p 是 int 类型指针
  2. 表达式中:*p是解引用操作符

解引用含义:①找到 p 里面存的内存地址 ②从这个地址往后取 sizeof (类型) 个连续字节 ③把取出的这片内存,当做对应类型的数据

指针分类 普通变量指针:int、char、double* 数组指针:int (p)[10],存放整个数组的地址 指针的指针:int**,存放另一个指针变量的地址 结构体指针:struct stu函数指针:保存函数的内存地址(后面回调函数学习)

示例:int (*pfunc)(int);就是函数指针的写法

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询