C语言学习: 结构体的内存对齐

怎么对齐的? 是对齐他占用内存的倍数, 看下面的代码

int main() {
  typedef struct Person {
    char *name;
    int age;
    char *id;
  } Person;

  struct Person person = {.name="bennyhuo", .id="12113322222"};
View Code

指针变量占用八个字节,int占4个字节, 大家看到最后八个字节对应的是 id指针,前面有cc cc cc cc, 这四个字节就是内存对齐导致的。

换种写法,优化结构体对齐的问题。 从这个例子可以看出, 结构体定义不合理的话, 会导致内存浪费。

 1 typedef struct {
 2     char a; // 1
 3     char b; // 1
 4 //    __attribute((aligned(2))) int c; // 4 gcc only
 5 //    _Alignas(8) int c; // 4 c11
 6     int c;
 7     short d; // 2
 8     double e; // 8
 9   } Align;
10 
11   typedef struct {
12     char a; // 1
13     char b; // 1
14     short d; // 2
15     int c; // 4
16     double e; // 8
17   } OptimizedAlign;
18 
19 
20   Align align = {'a', 'b', 3, 4, 5.0};
21   OptimizedAlign optimized_alignlign = {'a', 'b', 4, 3, 5.0};

看下面的内存分配, 第一版, int c 在short d前面,int 展占4位, short占2位,double占八位, 所以在分配e的时候,会让出6个cc, 放在第二行第八位,导致了红框部分内存的浪费。

align 和optimizeAlign,的区别, 就是把d移到c的前面定义, 这样, char, char, short, 就正好放在前四个字节上, int正好4个字节, 就避免了红框部署的浪费。

 

 

 怎么设置全局的内存对齐。

#pragma pack(2)

 

 

 设置前

 

 

 设置后, id指针的位置向前移了, 他变成2的倍数进行对齐, 而不是八位对齐。

 

 

 怎么设置单个字段的对齐方式呢: _Alignas

_Alignas(8) int c; // 4 c11
 1 typedef struct {
 2     char a; // 1
 3     char b; // 1
 4 //    __attribute((aligned(2))) int c; // 4 gcc only
 5     _Alignas(8) int c; // 4 c11
 6 //    int c;
 7     short d; // 2
 8     double e; // 8
 9   } Align;
10 
11   typedef struct {
12     char a; // 1
13     char b; // 1
14     int c; // 4
15     short d; // 2
16     double e; // 8
17   } OptimizedAlign;
18 
19 
20   Align align = {'a', 'b', 3, 4, 5.0};
21   OptimizedAlign optimized_alignlign = {'a', 'b', 4, 3, 5.0};
View Code

对齐前后,可以看到,上面的绿色部分是设置了八位对齐,下面的绿色部分是默认, 我们把int c改成八位对齐, 所以变成下面这样。

 

 

 怎么看一个字段对于这个结构体的内存偏移量: 用 offsetof(Align,e)

 

 

 整体代码

 1 #include <stdio.h>
 2 #include <io_utils.h>
 3 #include <stddef.h>
 4 //#pragma pack(2)
 5 int main() {
 6   typedef struct Person {
 7     char *name;
 8     int age;
 9     char *id;
10   } Person;
11 
12   struct Person person = {.name="bennyhuo", .id="12113322222"};
13 
14   PRINT_INT(person.age);
15   person.age = 30;
16 
17   typedef struct {
18     char a; // 1
19     char b; // 1
20 //    __attribute((aligned(2))) int c; // 4 gcc only
21     _Alignas(8) int c; // 4 c11
22 //    int c;
23     short d; // 2
24     double e; // 8
25   } Align;
26 
27   typedef struct {
28     char a; // 1
29     char b; // 1
30     int c; // 4
31     short d; // 2
32     double e; // 8
33   } OptimizedAlign;
34 
35 
36   Align align = {'a', 'b', 3, 4, 5.0};
37   OptimizedAlign optimized_alignlign = {'a', 'b', 4, 3, 5.0};
38 
39   //PRINT_INT(_Alignof(align.c));
40   PRINT_INT(offsetof(Align, e));
41   return 0;
42 }
View Code

结果

为什么要有内存对齐? 内存对齐之后, CPU访问内存会快一些

 

posted @ 2023-02-05 08:47  泥古拉斯赵四  阅读(40)  评论(0编辑  收藏  举报