内存对齐与内存开辟。结构体(struct),位段,枚举类型(enum),联合体(union)。

简介: 内存对齐与内存开辟。结构体(struct),位段,枚举类型(enum),联合体(union)

1.结构体内存对齐

(1)结构体内存对齐规则


a.第一个成员在与结构体变量偏移量为0的地址处


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


对齐数=编译器默认对齐数与该成员大小的较小值.


vs中默认值为8(如果没有默认对齐数 则默认对齐数为成员大小本身)


c.结构体总大小为最大对齐数的整数倍


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


(2)举例:

a.

int main()
{
  struct S1
  {
    char c1;  //1 8 对齐数为1  1字节
    int i;    //4 8 对齐数为4 要在偏移量4的整数倍处开辟 浪费3个字节 8字节
    char c2;  //1 8 对齐数为1  9字节 最后结构体大小要为最大对齐数4的整数倍 所以又浪费3字节 12字节
  };
  struct S1 s;
}

b.

#include<stdio.h>
int main()
{
  struct S2
  {
    char c1;//1 8 对齐数为1 1字节
    char c2;//1 8 对齐数为1 2字节
    int i;  //4 8 对齐数为4 要在偏移量为对齐数的整数倍处开辟 浪费两个字节 8字节
  };
  struct S2 s;
}

c.

int main()
{
  struct S3
  {
    double d;// 8 8 对齐数为8 8字节
    char c;  // 1 8 对齐数为1 9字节
    int  i;  // 4 8 对齐数为4 在12处开辟 16字节
  };
  struct S3 s;
}

d.

int main()
{
  struct S3
  {
    double d;// 8 8 对齐数为8 8字节
    char c;  // 1 8 对齐数为1 9字节
    int  i;  // 4 8 对齐数为4 在12处开辟 16字节
  };
  struct S4
  {
    char c1;     //1 8 对齐数为1 1字节
    struct S3 s3;//8 8 嵌套结构体对齐数为内结构体的最大对齐数8 在8处开辟8+16=24
    double d;    //8 8 对齐数为8 8+24=32 32字节 结构体大小为最大对齐数的整数倍
  };
  struct S4 s;
  
}

(3)内存对齐的原因


a.平台原因(移植原因)


不是所有的硬件平台都能访问任意地址上的任意数据。


b.性能原因


为了访问未对齐的内存,处理器要做两次内存访问。而对齐后的内存,处理器只需要访问一次。


(4)总结


如果要使结构体尽可能少的浪费空间,我们需要让占用空间小的成员尽量集中在一起。

2.位段

1.什么是位段?

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

a.位段的成员必须是:int ,unsigned int,signed int,char , unsigned char。

b.位段的成员名后边有一个冒号和一个数字。

int main()
{
  struct A
  {
    int _a : 2; //_a这个成员只占2个bit位 只能表示0 1 2 3
    int _b : 5; //_b这个成员只占5个bit位
    int _c : 10;
    int _d : 30;
  };
}

2.位段的空间是按照需要以4个字节或一个字节来开辟的

3.弊端:位段是不跨平台的.

3.枚举(一一列举)

利用枚举类型定义常量(比宏定义有优点)

int main()
{
  enum Color
  {
    RED = 5,
    GREEN = 8,
    BULE
  };          //一次可以定义多个常量
}

4.联合(共用体)

这些成员共用一块空间(同一时间只能使用一个!)

int main()
{
  union Un
  {
    char c;//c用的是i的第一个字节的空间
    int i; 
  };
  union Un un; //联合体大小至少是最大成员的大小
}

1.联合体的大小(要对齐)

int main()
{
  union Un
  {
    short arr[7];// 14 2 
    int i;//4   4  
    }u;//本来14个一节就够了 但是联合体需要对其 
      //到最大对齐数4的整数倍 所以为 16个字节
}

2.利用联合体判断大小端

#include<stdio.h>
int main()
{
  union Un
  {
    char c;
    int i;
  }u;
  u.i = 1;
  if (u.c == 1)
  {
    printf("小端\n");
  }
  else
  {
    printf("大端\n");
  }
}


目录
相关文章
|
7月前
|
编译器 C语言 C++
【C语言】realloc()函数详解(动态内存开辟函数)
【C语言】realloc()函数详解(动态内存开辟函数)
100 0
|
7月前
|
存储 编译器 Linux
匿名结构体类型、结构体的自引用、结构体的内存对齐以及结构体传参
匿名结构体类型、结构体的自引用、结构体的内存对齐以及结构体传参
|
29天前
|
存储 Java 程序员
结构体和类的内存管理方式在不同编程语言中的表现有何异同?
不同编程语言中结构体和类的内存管理方式既有相似之处,又有各自的特点。了解这些异同点有助于开发者在不同的编程语言中更有效地使用结构体和类来进行编程,合理地管理内存,提高程序的性能和可靠性。
25 3
|
1月前
|
存储 缓存 Java
结构体和类在内存管理方面的差异对程序性能有何影响?
【10月更文挑战第30天】结构体和类在内存管理方面的差异对程序性能有着重要的影响。在实际编程中,需要根据具体的应用场景和性能要求,合理地选择使用结构体或类,以优化程序的性能和内存使用效率。
|
1月前
|
存储 缓存 算法
结构体和类在内存管理方面有哪些具体差异?
【10月更文挑战第30天】结构体和类在内存管理方面的差异决定了它们在不同的应用场景下各有优劣。在实际编程中,需要根据具体的需求和性能要求来合理选择使用结构体还是类。
|
4月前
|
存储 Go
Go 内存分配:结构体中的优化技巧
Go 内存分配:结构体中的优化技巧
|
6月前
|
编译器 测试技术 C语言
【C语言】:自定义类型:结构体的使用及其内存对齐
【C语言】:自定义类型:结构体的使用及其内存对齐
76 7
|
6月前
|
存储 编译器 C语言
C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)一
C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)一
63 2
|
6月前
|
C语言
C语言学习记录——动态内存开辟常见的错误
C语言学习记录——动态内存开辟常见的错误
36 1
|
6月前
|
编译器 Linux C语言
C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)二
C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)二
54 1