13.高级内存

📅 发布时间:2026/10/7 16:23:38
13.高级内存
前置知识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 ~ 127short%hd2 字节 (16bit)-32768 ~ 32767int%d4 字节 (32bit)-2147483648 ~ 2147483647long%ld4 字节 (32bit)-2147483648 ~ 2147483647long 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 ~ 255unsigned short%hu2 字节0 ~ 65535unsigned int%u4 字节0 ~ 4294967295unsigned long long%llu8 字节0 ~ 184467440737095516151.3 浮点数类型小数表格类型名打印符字节内存拆分 (SEM)指数偏移值float单精度%f4 字节1 符号位 8 指数位 23 尾数位127double双精度%lf8 字节1 符号位 11 指数位 52 尾数位1023小提示你直接写 0.5C 语言默认当成 double想要 float 小数写成 0.5f。第二章 原码、反码、补码重中之重铁律计算机里面所有整数永远只保存【补码】 电脑减法不会做减法是转换成「加上负数的补码」用加法完成运算。1、原码 把十进制数字转成二进制最高位当做符号位 正数符号位 0后面写数字二进制 负数符号位 1后面写数字二进制例子32 位 int 10 原码00000000 00000000 00000000 00001010 -10 原码10000000 00000000 00000000 000010102、反码 正数反码 原码正数三样全部相等 负数符号位保持 1 不变剩下所有 0、1 互相取反-10 反码11111111 11111111 11111111 111101013、补码最终存入内存的数 正数补码 原码 反码 负数补码 反码 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负数→ 空位全部补 1char 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位前面全部补000000000 00000000 00000000 10000000第四章 无符号类型经典坑点坑 1无符号数永远≥0i-- 永远不会小于 0死循环unsigned int i; for(i 9; i 0; i--) { printf(%u\n, i); }当 i0再减一变成无符号最大值 4294967295永远大于等于 0 → 无限循环 同理unsigned char ii 从 0 再‑1 → 255循环永远不会结束。坑 2strlen 陷阱备注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 次一定会遇到数值等于 0strlen 碰到 0 停止。第五章 浮点数 float /double 在内存如何存储IEEE‑754小数存储公式\((-1)^S × M × 2^E\)S符号位0 正数、1 负数 M尾数范围固定 [1, 2)备注这个1.xxxx前面的 1 叫做隐藏位存入内存时省略读取数据的时候自动补上。 E2 的指数注意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 S1真实 E3真实 M1.01011步骤 4转换成电脑存储版本 S 不变1 存储 E 3 127 130二进制10000010 存储 M丢掉小数点前的 1取 01011后面补 0 凑满 23 位 → 01011000000000000000000步骤 5拼接 1823 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 字节 和 * 变量名取出变量第一个字节的地址有两层身份定义变量时int *p;代表 p 是 int 类型指针表达式中*p是解引用操作符解引用含义①找到 p 里面存的内存地址 ②从这个地址往后取 sizeof (类型) 个连续字节 ③把取出的这片内存当做对应类型的数据指针分类 普通变量指针int、char、double* 数组指针int (p)[10]存放整个数组的地址 指针的指针int**存放另一个指针变量的地址 结构体指针struct stu函数指针保存函数的内存地址后面回调函数学习示例int (*pfunc)(int);就是函数指针的写法