迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > C语言 >

在 C 语言中使用结体构对齐和填充

作者:迹忆客 最近更新:2023/05/05 浏览次数:

本文将介绍几种在 C 语言中使用结构体来对齐和填充的方法。


了解 C 语言中对齐和填充的基础知识

内存中的所有对象都以主要数据类型表示,如:charshortintlongpointer 等。charshortintlongpointer 等。这些数据类型在内存中都有其相应的大小。在大多数当代 64 位桌面处理器上,char 的大小是 1 个字节,short 是 2 个字节,int 是 4 个字节,pointer 是 8 个字节,以此类推。请注意,这些都不是保证大小(除了 char),但可以使用 sizeof 操作符检索对象的大小。现在,对齐是编译器用来放置内存中的变量的方法,意味着每个基本数据类型都存储在被相应大小除以的地址上。

通常,利用对齐来更快、更有效地访问数据对象。对齐迫使连续声明的不同数据类型在其地址之间包含一些间距。也就是说,如果我们声明一个结构 st1,其中有一个指针和一个 char,如下面的例子所示,它总共会占用 16 个字节。不过要注意,一个指针需要 8 个字节,一个 char 需要一个字节,所以人们会认为 st1 结构一定会占用 9 个字节。但它的表现就像所有成员都是按照最大成员的大小(即 8 个字节)对齐的。st2 结构展示了一个类似的结构,它占据了同样的内存量,只是它有一个 7 个 char 成员的数组。

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char const *argv[]) {

    typedef struct {
        char *p;
        char c2;
    } st1;

    typedef struct {
        char *p;
        char c2;
        char padding[7];
    } st2;

    printf("sizeof st1 = %zu\n", sizeof(st1));
    printf("sizeof st2 = %zu\n", sizeof(st2));

    exit(EXIT_SUCCESS);
}

输出:

sizeof st1 = 16
sizeof st2 = 16

在 C 语言中使用成员重新排序技术来节省对象的空间

前面的例子表明,当结构包括不同类型,并且没有填满对齐边界时,会有一些内存的浪费。虽然,在某些情况下,可能会重新排列结构成员,节省额外的空间。

接下来的示例代码中定义了 foo1 结构,它的中间是最大的成员(char *),而 foo2 结构的成员与第一个结构相同。这两个对象的大小是不同的–24 字节和 16 字节。这与数据成员的排序有关。在 foo1 结构中,p 需要在被 8 整除的地址上对齐,所以前面的 intshort 总共会占用 8 个字节,后面的两个 char 也会占用这 8 个字节。虽然,如果我们把 p 移到第一位,下面的成员将挤进 8 个字节,也满足对齐规则。这样,foo2 的大小一共是 16 个字节,就叫打包 struct。请注意,gcc 编译器有特殊的 __attribute__((packed)) 指定符,该说明符甚至可以强制打包无序的 struct 成员。

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char const *argv[]) {

    typedef struct {
        int n1;
        short s1;
        char *p;
        char c1;
        char c2;
    } foo1;

    typedef struct {
        char *p;
        int n1;
        short s1;
        char c1;
        char c2;
    } foo2;

    typedef struct {
        int n1;
        short s1;
        char *p;
        char c1;
        char c2;
    } __attribute__((packed)) foo3;

    printf("sizeof foo1 = %zu\n", sizeof(foo1));
    printf("sizeof foo2 = %zu\n", sizeof(foo2));
    printf("sizeof foo3 = %zu\n", sizeof(foo3));

    exit(EXIT_SUCCESS);
}

输出:

sizeof foo1 = 24
sizeof foo2 = 16
sizeof foo3 = 16

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

在 C 语言中使用 typedef enum

发布时间:2023/05/07 浏览次数:181 分类:C语言

本文介绍了如何在 C 语言中使用 typedef enum。使用 enum 在 C 语言中定义命名整数常量 enum 关键字定义了一种叫做枚举的特殊类型。

C 语言中的静态变量

发布时间:2023/05/07 浏览次数:151 分类:C语言

本文介绍了如何在 C 语言中使用静态变量。在 C 语言中使用 static 变量在函数调用之间保存变量值

C 语言中生成随机数

发布时间:2023/05/07 浏览次数:64 分类:C语言

本文演示了如何在 C 语言中生成随机数。使用 rand 和 srand 函数在 C 语言中生成随机数

C 语言中的 i++ 与++i

发布时间:2023/05/07 浏览次数:83 分类:C语言

本文演示了如何在 C 语言中使用前缀增量与后缀增量运算符。C 语言中++i 和 i++ 记号的主要区别

C 语言中获取当前工作目录

发布时间:2023/05/07 浏览次数:182 分类:C语言

本文演示了如何在 C 语言中获取当前工作目录。使用 getcwd 函数获取当前工作目录的方法

C 语言中的位掩码

发布时间:2023/05/07 浏览次数:126 分类:C语言

本文介绍了如何在 C 语言中使用位掩码。使用 struct 关键字在 C 语言中定义位掩码数据

C 语言中的排序函数

发布时间:2023/05/07 浏览次数:181 分类:C语言

本文演示了如何在 C 语言中使用标准库排序函数。使用 qsort 函数对 C 语言中的整数数组进行排序

C 语言中的 extern 关键字

发布时间:2023/05/07 浏览次数:114 分类:C语言

本文介绍了如何在 C 语言中使用 extern 关键字。C 语言中使用 extern 关键字来声明一个在其他文件中定义的变量

C 语言中的 #ifndef

发布时间:2023/05/07 浏览次数:186 分类:C语言

本文介绍了如何在 C 语言中使用 ifndef。在 C 语言中使用 ifndef 保护头文件不被多次包含 C 语言中的头文件用于定义同名源文件中实现的函数的接口。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便