数据存储和内存对齐

校内课复习笔记

非数值数据表示

在计算机中,只有01序列,这串01序列是什么意思,由人为定义。

西文字符

在ASCII码中,通过一个65的偏移量,使得一部分无符号数指向A-Za-z。

在C语言中,通过char类型的转换规范,可以将对应的01序列转换为英文输出。

GB2312-80

需要了解三种码之间的关系:区位码、国标码、机内码

国标码=区位码+2020H

机内码=区位码+8080H

区位码该怎么求呢?加就完了!

区是从A1开始的:第1区就是A1,第2区就是A2...第N区就是(A0+N)H

位也是从A1开始的:第1个字就是A1,第2个字就是A2...第N个字就是(A0+N)H

区位码就是区和位拼接。

比如知道了"啊"字位于第16区第1位,那么就能得到它的区位码为B0A1H

字模点阵

如果人为指定了某个01串对应的文字含义。那么如何显示出来呢,就需要用到字库。

需要提前将字形存在机内。不同字体对应不同的字库,从字库中找到字形描述信息,然后送设备输出。

通过在字库中的位置找相应的字形信息。

大端存储和小端存储

在之前"码值"的博客中,对数据存储留了个坑。

给变量a赋值0x123456,结果在内存中存储的是0x56341200

这是因为,当前编译器,采用的是"小端存储"。

比如这道题:某计算机字长为32位,按字节编址,采用小端(Little Endian)方式存放数据。假定有一个double型变量,其机器数表示为1122 3344 5566 7788H,存放在0000 8040H开始的连续存储单元中,则存储单元0000 8046H中存放的是22H

如果是按十六进制顺序存贮,如0x00123456,此时为大端存储。

也就是说:

  • 小端存储的时候,数据的表示和存储顺序是相反的。也就是低位在前。
  • 大端存储的时候,数据的表示和存储顺序是相同的。也就是高位在前。

上面的例子给人的感觉不是很直观:0x12345656在前,为什么还是小端?

这是因为,56在写数字的时候,是在低位的位置上,越往左,位权越大。

大端小端各自的优点

  • 小端方式强制类型转换不需要调整
  • 大端容易判断正负

小端是将低位放在低地址,高位放在高地址。在发生类型转换时,丢失的是高位的数据。因此小端方式存储,只需要知道首地址,向后裁剪或扩充就可以。

大端是将高位放在低地址,低位放在高地址。有符号数的最高位是符号位。如果采用大端存储,只需要知道首地址指向的值,也就是知道了最高位的符号位。

存储方式检测

上面的配图直接截自Clion。

在C语言中可以利用联合检测。

c 复制代码
union A{
    int a;
    char b;
};
union A a;
a.a=0x123456;
printf("%hhx",a.b);

利用联合,对a赋值。

然后利用b去除第一个字节部分的值。

内存对齐

创建一个结构体,在里面定义各种变量,变量的定义顺序会影响结构体最终占用的空间。

c 复制代码
#include "stdio.h"

struct A {
    char name[20];  //20  16+4
    int age;        //4   4+上面的4
    double score;   //8   8
};
struct B {
    char name[20];  //20  16+4 补4
    double score;   //8
    int age;        //4   补4
};
struct AB {
    struct A a;
    struct B b;
};
struct BA {
    struct B b;
    struct A a;
};

int main() {
    struct A a;
    struct B b;
    struct AB ab;
    struct BA ba;
    printf("A的大小=%d\n", sizeof(a));
    printf("B的大小=%d\n", sizeof(b));
    printf("AB的大小=%d\n", sizeof(ab));
    printf("BA的大小=%d\n", sizeof(ba));
    return 0;
}

上面代码的运行结果:

有如下要点:

  • 字符可以拆分
  • 字符可以和整形变量合并
  • 结构体内嵌套结构体,占用空间不变:结构体本身已经进行了内存对齐

考虑内存对齐,只需要考虑基本数据类型的对齐。

尽量把大的内存放到后面写。

联合体中各个变量共用同一段内存。选中占用空间最大的变量对齐。

相关推荐
疯狂飙车的蜗牛24 分钟前
从零玩转CanMV-K230(4)-小核Linux驱动开发参考
linux·运维·驱动开发
建投数据1 小时前
建投数据与腾讯云数据库TDSQL完成产品兼容性互认证
数据库·腾讯云
迷雾漫步者1 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-1 小时前
验证码机制
前端·后端
Hacker_LaoYi2 小时前
【渗透技术总结】SQL手工注入总结
数据库·sql
岁月变迁呀2 小时前
Redis梳理
数据库·redis·缓存
独行soc2 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍06-基于子查询的SQL注入(Subquery-Based SQL Injection)
数据库·sql·安全·web安全·漏洞挖掘·hw
燃先生._.2 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
你的微笑,乱了夏天2 小时前
linux centos 7 安装 mongodb7
数据库·mongodb
远游客07133 小时前
centos stream 8下载安装遇到的坑
linux·服务器·centos