C语言教程
C语言控制语句
C语言函数
C语言数组
C语言指针
C语言字符串
C语言数学函数
C语言结构
C语言文件处理
C预处理器

C语言结构填充

C中的结构填充是一种概念,它在内存地址之间添加一个或多个空字节以对齐内存中的数据。
让我们首先通过以下简单场景了解 C 中的结构填充:
假设我们创建了一个用户定义的结构。当我们创建这种结构的对象时,连续的内存将分配给该结构成员。
struct student
{
   char a;
   char b;
   int c;
} stud1;
在上面的示例中,我们创建了一个类型为学生的结构。我们已将此结构的对象声明为" stud1 "。创建对象后,将连续的内存块分配给其结构成员。首先,将内存分配给' a '变量,然后分配给' b '变量,然后分配给'c '变量。

结构学生的大小是多少?

现在,我们计算结构学生的大小。我们假设int的大小为4个字节,而char的大小为1个字节。
struct student
{
  char a; // 1 byte
  char b; // 1 byte
  int c; // 4 bytes 
}
在上述情况下,当我们计算 struct student 的大小时,大小为6个字节。但是这个答案是错误的。现在,我们将理解为什么这个答案是错误的?我们需要了解结构填充的概念。

结构填充

处理器一次不会读取1个字节。它一次读取1个字。
1个字是什么意思?
如果我们有32位处理器,则处理器读取4个字一次一个字节,这意味着1个字等于4个字节。
1 word = 4 bytes
如果我们有64位处理器,则该处理器一次读取8个字节,这意味着1个字等于8个字节。
因此,我们可以说
1 word = 8 bytes
一个32位处理器能够一次访问4个字节,而64位处理器能够一次访问8个字节。

为什么要填充结构?

struct student
{
  char a; // 1 byte
  char b; // 1 byte
  int c; // 4 bytes 
}
如果我们有32位处理器(一次4个字节),则上述结构的内存的图形表示为:
C
中的结构填充如上图所示,我们知道结构占用了连续的内存块,即char a为1字节,char为1字节对于char b,对于int c是4个字节,那么在这种情况下,我们将面临什么问题。

出了什么问题?

4个字节可以我们正在考虑使用32位架构时一次访问。问题在于,在一个CPU周期中,一个字节的 char a ,一个字节的 char b 和2个字节的 int c 可能是访问。在访问 char a 和 char b 时,我们不会遇到任何问题,因为两个变量都可以在一个 CPU 周期,但是当我们访问 int c 变量时,我们将面临问题,因为需要2个CPU周期才能访问'c '变量。在第一个CPU周期中,访问前两个字节,在第二个周期中,访问其他两个字节。
假设我们不想访问'a'和'b'变量,我们只想访问变量" c",这需要两个周期。变量" c"为4个字节,因此也可以在一个周期内访问它,但是在这种情况下,它使用2个周期。这是不必要的CPU周期浪费。由于这个原因,引入了结构填充概念以节省CPU周期数。结构填充由编译器自动完成。现在,我们将看到如何完成结构填充。

结构填充是如何完成的?

C
中的结构填充为了实现结构填充,如上图所示,在左侧创建了一个空行,并在其中占用了两个字节。左侧的" c"变量向右移动。因此,'c'变量的所有四个字节都在右侧。现在,可以在单个CPU周期中访问'c'变量。在进行结构填充之后,结构占用的总内存为8个字节(1个字节+ 1个字节+2个字节+4个字节),大于前一个字节。尽管在这种情况下会浪费内存,但是可以在一个周期内访问变量。
让我们创建一个简单的结构程序。
#include <stdio.h>
struct student
{
   char a;
   char b;
   int c;
};
int main()
{
   struct student stud1; // variable declaration of the student type..
   // Displaying the size of the structure student.
   printf("The size of the student structure is %d", sizeof(stud1));
   return 0;
}
在上面的代码中,我们创建了一个名为" 学生"的结构。在 main()方法中,我们声明一个学生类型的变量,即 stud1 ,然后我们使用 sizeof( )运算符。由于上面已经讨论了结构填充的概念,因此输出将为 8字节。
输出
C的结构填充

变量的更改顺序

现在,我们将看到更改变量顺序时会发生什么,它是否影响程序的输出。让我们考虑相同的程序。
#include <stdio.h>
struct student
{
   char a;
   int b;
  char c;
};
int main()
{
   struct student stud1; // variable declaration of the student type..
   // Displaying the size of the structure student.
   printf("The size of the student structure is %d", sizeof(stud1));
   return 0;
}
上面的代码与之前的代码相似;我们唯一更改的是结构学生中变量的顺序。由于顺序的变化,两种情况下的输出都会不同。在前一种情况下,输出为8个字节,但是在这种情况下,输出为12个字节,如下面的屏幕快照所示。
输出
C中的结构填充
现在,我们需要了解" 为什么输出不同这种情况"。
首先,将内存分配给 char a 变量,即1个字节。
C的结构填充
现在,内存将分配给 int b ,因为 int 变量占用4个字节,但左侧只有3个字节可用。空行将在这3个字节上创建,而int变量将占据其他4个字节,以便可以在单个CPU周期中访问整数变量。
C的结构填充
现在,内存将分配给 char c ,一次,CPU可以访问1个字,等于4个字节,因此CPU将使用4个字节来访问'c'。变量。因此,所需的总内存为12个字节(4个字节+4个字节+4个字节),即访问 char a 变量需要4个字节,访问 int b 则需要4个字节。 strong>变量,以及访问单个字符' c '所需的其他4个字节。
C的结构填充

如何避免在C语言中进行结构填充?

结构填充是编译器自动完成的内置过程。有时需要避免在C中进行结构填充,因为它会使结构的大小大于结构成员的大小。
我们可以通过两种方式避免在C中进行结构填充:
使用#pragma pack(1)指令 使用属性
使用#pragma pack(1)指令
#include <stdio.h>
#pragma pack(1)
struct base
{
    int a;
    char b;
    double c;
};
int main()
{
  struct base var; // variable declaration of type base
  // Displaying the size of the structure base
  printf("The size of the var is : %d", sizeof(var));
return 0;
}
在上面的代码中,我们使用了 #pragma pack(1)指令来避免结构填充。如果我们不使用此指令,那么上面程序的输出将是16个字节。但是结构成员的实际大小为13个字节,因此浪费了3个字节。为避免浪费内存,我们使用 #pragma pack(1)指令提供1字节的打包。
输出
C语言中的结构填充 使用属性
#include <stdio.h>
struct base
{
    int a;
    char b;
    double c;
}__attribute__((packed));  ;
int main()
{
  struct base var; // variable declaration of type base
  // Displaying the size of the structure base
  printf("The size of the var is : %d", sizeof(var));
    return 0;
}
输出
C语言中的结构填充
昵称: 邮箱:
Copyright © 2022 立地货 All Rights Reserved.
备案号:京ICP备14037608号-4