Cprogramming 简明教程
Structure Padding and Packing in C
What is Structure Padding in C?
C 中的 Structure 填充是由 CPU architecture 处理的过程。结构填充在结构内添加一定数量的空字节,以便数据成员在内存中自然对齐。对齐要求由处理器架构而不是语言本身决定。自然,对齐要求会根据数据总线大小或特定 CPU 架构的其他架构考虑因素而更改。
Structure padding in C is the process that is handled by the CPU architecture. Structure Padding adds a certain number of empty bytes within a structure so that the data members are naturally aligned in memory. The alignment requirements are determined by the processor architecture rather than the language itself. Naturally, the alignment requirements change as per the data bus size or other architectural considerations of a certain CPU architecture.
Understanding Structure Padding with Examples
我们先定义结构类型如下 −
Let us define a struct type as follows −
struct struct1 {
char x;
int y;
char z;
};
Example 1
让我们检查此类型变量所需的字节数 −
Let us check the size in bytes required for a variable of this type −
#include <stdio.h>
struct struct1{
char a;
char b;
int c;
};
int main(){
printf("Size: %d", sizeof(struct struct1));
return 0;
}
当你运行这段代码时,它将产生以下输出:
When you run this code, it will produce the following output −
Size: 8
结果与预期相反。
The result is contrary to the expectation.
考虑到 char 类型需要 1 个字节,而 int 类型需要 4 个字节,人们可能会认为输出应该是“1 + 1 + 4 = 6 个字节”。
Considering that a char type needs 1 byte, and an int type needs 4 bytes, one might assume the output should be "1 + 1 + 4 = 6 bytes".
然而,CPU 架构有必要更改此结构。考虑到我们正在使用具有 32 位处理器的 CPU,它一次读取 4 个字节,这意味着 1 个字等于 4 个字节。
However, the CPU architecture necessitates altering this structure. Considering that we are using a CPU with 32-bit processor, it reads 4 bytes at a time, which means that 1 word is equal to 4 bytes.
在一次 CPU 周期中,它访问字符“a”,然后字符“b”和整数“c”的前两个字节。在第二个周期中,访问另外两个字节。
In one CPU cycle, it accesses the char "a", then char "b" and the first two bytes of int "c". In the second cycle, the other two bytes are accessed.
即使我们只想读取“c”,也需要两个 CPU 周期。为此,CPU 在存储“c”值所在字节之前添加两个空字节。此机制称为 padding 。
Even if we want to read only "c", two CPU cycles are required. For this purpose, the CPU adds two empty bytes before the bytes in which the value of "c" is stored. This mechanism is called as padding.
这解释了我们在上面获得的结果,即结构类型的尺寸为 8 个字节。
This now explains the result we obtained above, that of the size of the struct type to be 8 bytes.
Example 2
让我们更改上述结构类型的成员顺序,并将“ b ”的类型和“ c ”的类型设置如下。
Let us change the sequence of members in the above struct type, and set the type of "b" and the type of "c".
#include <stdio.h>
struct struct1{
char a;
int b;
char c;
};
int main(){
printf("size: %d", sizeof(struct struct1));
return 0;
}
运行代码并检查其输出:
Run the code and check its output −
size: 12
在前一个字的 4 个字节中,第一个字节分配给字符“a”,后跟三个空字节。
Out of the 4 bytes in the first word, the first one is allocated to char "a" followed by three empty bytes.
形成下一个字的下一个 4 个字节用于存储整数“b”。随后,在下一组 4 个字节中,仅一个字节用于“c”。然而,结构大小为 12。
The next 4 bytes that form the next word are used to store int "b". Subsequently, out of the next group of 4, only one is utilized for "c". However, the struct size is 12.
What is Structure Packing in C?
另一方面,结构打包是一种最小化填充影响的机制,从而试图减少浪费的内存空间。我们可以使用某些编译指示和属性来实现打包。
Structure packing, on the other hand, is a mechanism for minimizing the effect of padding, thereby trying and reduce wasted memory space. We can use certain pragma directives and attributes to achieve packing.
Understanding Structure Packing with Examples
由 CPU 架构强制的填充是不可避免的,但是有办法最小化填充。可以使用以下方法来完成 −
The padding, forced by the CPU architecture is unavoidable, however there are ways to minimize padding. It can be done with the use of −
-
Using #pragma pack(1) directive
-
Using packed attribute
Using
#pragma pack(1) 预处理器指令强制编译器在内存分配过程中忽略填充,并将结构成员端对端对齐。
The #pragma pack(1) preprocessor directive forces the compiler to disregard the padding, and align the structure members end to end during the memory allocation process.
让我们在之前使用的代码顶部添加此指令,并查看结果 −
Let’s add this directive at the top of the code used previously, and see the result −
#include <stdio.h>
#pragma pack(1)
struct struct1{
char a;
int b;
char c;
};
int main(){
printf("size: %d", sizeof(struct struct1));
return 0;
}
运行代码并检查其输出:
Run the code and check its output −
size: 6
我们可以看到,避免了结构填充并减少了内存浪费。
We can see the structure padding has been avoided and reduced memory wastage.
Using _attribute_packed
通过 GCC,我们可以使用属性指定结构和联合类型的各种特殊属性。属性包括: aligned, deprecated, packed, transparent_union, unused 和 visibility 。应用这些属性的语法是“ attribute … ”。
With GCC, we can use attributes to specify various special properties of structure and union types. The attributes are: aligned, deprecated, packed, transparent_union, unused, and visibility. The syntax of applying these attributes is "attribute …".
在此,我们将在结构类型的定义中使用 packed 属性。
Here, we are going to use packed attribute in the definition of our struct type.
#include <stdio.h>
struct __attribute__((packed)) struct1{
char a;
int b;
char c;
};
int main(){
printf("size: %d", sizeof(struct struct1));
return 0;
}
运行代码并检查其输出:
Run the code and check its output −
size: 6
此方法还避免了填充的影响。
This method also avoids the effect of padding.