美文网首页C语言
【C进阶】内存对齐

【C进阶】内存对齐

作者: 不会编程的程序圆 | 来源:发表于2020-03-24 10:17 被阅读0次

码字不易,对你有帮助 点赞/转发/关注 支持一下作者
微信搜公众号:不会编程的程序圆
看更多干货,获取第一时间更新

想看更好的排版可以阅读原文

阅读原文

零 前言

自定义类型也就是:结构体,联合和枚举。这部分的基础知识在前面的文章中我们也详细的讲过。点击阅读

我们这一节主要来讲一相关的些比较重要的知识。

一 结构体

1. 内存对齐

Ⅰ)引入
struct S1
{
    char c1;
    int i;
    char c2;
};

上面是一个结构体,也是我们自定义的一种类型。我们知道,任何类型都有大小,那么结构体 S1 的大小是多少?

是结构体各成员变量大小的和吗?如果是的话,那结构体 S1 的大小就是 6

那我们设计一个程序验证一下:

int main(void) {

    printf("%d", sizeof(struct S1));

    return 0;
}

输出是:12,这个 12 是怎么得来的呢?

想要知道这个问题答案,那我们就要了解一下 内存对齐

Ⅱ)为什么要内存对齐?

内存对齐关系到 CPU 读取数据的效率 和 一些其他原因。我们这里不做展开,有兴趣可以自己查一下。

Ⅲ)规则
  • 第一个成员在与结构体变量偏移量为0的地址处。

  • 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。

对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值
VS中默认的值为8

  • 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。

  • 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

四)练习

判断下面结构体的大小:

VS 默认的对齐数是 8,32 位机器

1

struct S1
{
    char c1;
    int i;
    char c2;
};

解析:1(char) (+3(int 应该对齐到 4 的整数倍上,也就是 4,所以应该给 1 加上 3 凑成 4)) +4(int) +1(char) (+3最后整个结构体大小为最大对齐数(也就是 4)的整数倍处,所以结构体的大小不是 9 而是 12 )(最大对齐数是最大成员的对齐数,这个是前面算过的(成员大小和默认对齐数取小))

答案:12

2

struct S2
{
    char c1;
    char c2;
    int i;
};

第一个例题已经详细的分析了判断结构体大小的步骤,下面不再赘述。

1 (char)+ 1 (char) (+2) + 4 (int)

答案:8

3

struct S3
{
    double d;
    char c;
    int i;
}

8 (double) + 1 (char) (+3) + 4 (int)

答案:16

4

struct S3
{
    double d;
    char c;
    int i;
};

struct S4
{
    char c1;
    struct S3 s3;
    double d;
};

例 3 中,我们已经知道了 S3 的大小是 16

1 (char) (+ 7(结构体大小是 16 和 编译器默认对齐数 8 取较小值,所以结构体要对齐的整数倍是 8)) + 16 (S3) + 8 (double)

答案:32

不确定你可以自己在你的编译器上敲一下,看看运行结构,前提是编译器的默认对齐数是 8 ,如果不是,结果可能会不一样,那么编译器的默认对齐数可以修改吗?

2. 修改默认对齐数

只需要加上一条指令即可:

#pragma pack(4)//设置默认对齐数为4

如果你想取消设置的默认对齐数,还原为默认:

#pragma pack()

二 位段

1.了解位段

位段的声明和结构是类似的,有两个不同:

  1. 位段的成员必须是 int、unsigned int 或signed int 。
  2. 位段的成员名后边有一个冒号和一个数字。
struct S
{
    char a : 3;// a 的大小为 3 个比特位
    char b : 4;
    char c : 5;
    char d : 4;
};
int main(void) {

    struct S s = { 0 };
    
    // 可以像一般的结构体成员访问一样访问它们
    s.a = -4;// 3 个字节存储数的范围是 -4 ~ 3
    s.b = 7;
    s.c = 3;
    s.d = 4;


    printf("%d\n", s.a);

    return 0;
}

存储方式:

  1. 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型
  2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。
  3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段

位段的应用:

可以自行了解IP数据报格式

在 Github 上看更全的目录:

https://github.com/hairrrrr/C-CrashCourse

以后的这个系列的代码都会上传上去,欢迎 star


以上就是本次的内容。

如果文章有错误欢迎指正和补充,感谢!

最后,如果你还有什么问题或者想知道到的,可以在评论区告诉我呦,我可以在后面的文章加上你们的真知灼见​​。

关注我,看更多干货!

我是程序圆,我们下次再见。

相关文章

  • 【C进阶】内存对齐

    码字不易,对你有帮助 点赞/转发/关注 支持一下作者微信搜公众号:不会编程的程序圆看更多干货,获取第一时间更新 想...

  • sizeof与字节对齐

    参考 【面试题】sizeof引发的血案编译器与字节对齐c 语言字节对齐问题详解C/C++内存对齐内存存取粒度C和C...

  • 内存对齐

    在C语言柔性数组一文中,提到了内存对齐,于是想写篇文章总结总结内存对齐。 内存对齐 为什么需要内存对齐 计算机系统...

  • golang 和 C++ 的内存对齐

    golang 和 C++的内存对齐,基本一致,记住规则和对应类型的 size 即可 内存对齐规则 有效对齐值是固定...

  • C/C++内存对齐

    在面试或工作中,经常会遇到内存对齐的问题。这里结合我的理解谈一谈对内存对齐的理解。 1. 为什么要内存对齐,不对齐...

  • C面试-内存对齐

    参考: 【嵌入式时代】C语言面试题详解(第7节),不知道“内存对齐”的程序员是不合格的 转载自:C语言的内存对齐 ...

  • iOS进阶——iOS(Objective-C)内存管理·二

    iOS进阶——iOS(Objective-C)内存管理·二

  • c++内存对齐

    1、为什么要进行内存对齐呢? 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台...

  • C语言 内存对齐

    引言 先看一个例子: 请问Test_T占几个字节?如果你的回复是 1 + 4 = 5,那就错了。我们看下程序运行的...

  • 2.iOS底层学习之内存对齐

    学习了内存对齐之后的疑问?? 1.为啥要内存对齐?2.内存对齐的规则?3.内存对齐实例分析。 内存对齐的目的 上网...

网友评论

    本文标题:【C进阶】内存对齐

    本文链接:https://www.haomeiwen.com/subject/mkonyhtx.html