欢迎光临
我们一直在努力

结构体详解:类型定义、变量创建与内存对齐

一、什么是结构体

结构体是 C 语言中一种自定义的复合数据类型。它允许我们将不同类型的数据组合在一起,形成一个新的整体。

例如,我们可以用结构体来描述一个 “学生”,它可以包含姓名(字符串)、学号(整数)和成绩(浮点数)等不同类型的信息。

二、结构体类型的定义

定义结构体的语法如下:

struct 结构体名 {
数据类型 成员名1;
数据类型 成员名2;
// … 更多成员
};

以 “学生” 为例:

struct Student {
char name[20]; // 姓名
int id; // 学号
float score; // 成绩
};

注:这个操作只是定义了一个新的数据类型,并没有分配实际的内存空间。

三、结构体变量的创建和初始化

1. 变量创建

我们可以通过两种方式创建结构体变量:

1.定义类型后单独声明变量:

// 先定义类型
struct Student {
char name[20];
int id;
float score;
};
// 再声明变量
struct Student stu1, stu2;

2.定义类型的同时声明变量

struct Student {
char name[20];
int id;
float score;
} stu1, stu2;

2. 初始化

我们可以在创建变量时直接对其初始化,常见方式有:

1.按成员顺序初始化:

struct Student stu1 = {"张三", 2024001, 92.5};

2.指定成员初始化(C99 及以上支持):

struct Student stu2 = {.id = 2024002, .name = "李四", .score = 88.0};

3.指针方式动态分配并初始化:

#include <stdlib.h>
struct Student *stu3 = (struct Student*)malloc(sizeof(struct Student));
stu3->id = 2024003;
stu3->score = 95.0;

四、结构体的内存对齐

结构体的内存布局并不是简单地将各成员的大小相加。为了提升 CPU 的访问效率,编译器会对结构体成员进行内存对齐。

1. 对齐规则

  • 数据成员对齐规则:结构体的第一个成员放在偏移量为 0 的位置。之后每个成员的起始地址必须是其自身对齐数的整数倍。对齐数 = 编译器默认的对齐数(通常为 8)与该成员大小的较小值。
  • 结构体整体对齐规则:结构体的总大小必须是其最大对齐数的整数倍。最大对齐数是结构体所有成员的对齐数中最大的那个。
  • 2. 内存布局示例

    struct Example {
    char a; // 1字节
    int b; // 4字节
    short c; // 2字节
    };

    假设编译器默认对齐数为 8:

  • char a 放在偏移量为 0 的位置,占用 1 字节。
  • int b 的对齐数为 4,因此它的起始地址必须是 4 的倍数。编译器会在 a 后面填充 3 个字节,让 b 从偏移量 4 开始,占用 4 字节(偏移量 4-7)。
  • short c 的对齐数为 2,它的起始地址是 8(是 2 的倍数),占用 2 字节(偏移量 8-9)。
  • 此时总占用字节数为 10,但结构体的最大对齐数是 4,所以整体大小需要是 4 的整数倍,最终会再填充 2 个字节,总大小为 12 字节。
  • a 0 0 0 b b b b c c 0 0

    3.内存分布图:

    a表示字符a占的字节,b表示整形b占的字节,c表示短整型c占的字节,0表示浪费的空间。

    4. 注意事项

    1.使用#pragma pack(n)可以手动设置对齐数为n,以减少内存浪费。

    2.内存对齐是空间换时间的策略,在需要高性能的场景下非常重要。

    五、小结:

    总的来说,结构体是 C 语言中组织复杂数据的核心工具,而理解内存对齐则是深入掌握结构体的关键一步,对开发高性能、低内存消耗的程序具有重要意义。

    对此,如果你有更好的内存对齐优化技巧,或者在实际项目中遇到过结构体内存布局的 “坑”,欢迎在评论区分享你的解决方案和踩坑经历!

    赞(0)
    未经允许不得转载:171主机测评 » 结构体详解:类型定义、变量创建与内存对齐
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址