C语言中的结构填充

C语言中的结构填充,c,structure,C,Structure,如果我在C中有一个结构定义 typedef struct example { char c; int ii; int iii; }; 当我声明上述结构类型的变量时,应该分配什么内存。 示例ee 还有什么是结构填充?如果存在与结构填充相关的任何风险?在正常32位下,它应该需要12个字节-将填充c字段。然而,这取决于体系结构和编译器 编译器始终可以使用pragma来声明结构的对齐方式(对于某些编译器,请更改默认对齐方式)。在正常32位下,它应该需要12个字节-将填充c字段。然而,这取

如果我在C中有一个结构定义

typedef struct example 
{
  char c;
  int ii;
  int iii;
};
当我声明上述结构类型的变量时,应该分配什么内存。 示例ee


还有什么是结构填充?如果存在与结构填充相关的任何风险?

在正常32位下,它应该需要12个字节-将填充
c
字段。然而,这取决于体系结构和编译器


编译器始终可以使用
pragma
来声明结构的对齐方式(对于某些编译器,请更改默认对齐方式)。

在正常32位下,它应该需要12个字节-将填充
c
字段。然而,这取决于体系结构和编译器


编译器始终可以使用
pragma
声明结构的对齐方式(对于某些编译器,请更改默认对齐方式)。

试试。在不同的系统上可能会有所不同

#include <stdio.h>
#include <stddef.h> /* for offsetof */
struct example { char c; int ii; int iii; };
int main(int argc, char *argv[])
{
    printf("offsetof(struct example, c) == %zd\n", offsetof(struct example, c));
    printf("offsetof(struct example, ii) == %zd\n", offsetof(struct example, ii));
    printf("offsetof(struct example, iii) == %zd\n", offsetof(struct example, iii));
    return 0;
}
请注意,
sizeof(char)==1
,但在
ii
字段之前有四个字节。额外的三个字节是填充。存在填充以确保数据类型排列在处理器的正确边界上

如果处理器进行未对齐的访问,可能会发生各种情况:

  • 访问速度较慢(大多数x86)
  • 访问必须由内核处理,速度非常慢(各种PowerPC)(这导致一些计算机游戏在速度较快的PPC603处理器上运行非常慢,而在速度较慢的PPC601处理器上运行得很好。)
  • 程序崩溃(各种SPARC)

我知道填充物没有已知的风险。真正发生的唯一问题是,使用不同编译器编译的两个程序(已知GCC和MSVC会导致这种情况)使用不同的填充,并且不能共享结构。如果来自不同编译器的代码链接在一起,这也会导致崩溃。由于填充通常由平台ABI指定,所以这种情况很少出现。

试试看。在不同的系统上可能会有所不同

#include <stdio.h>
#include <stddef.h> /* for offsetof */
struct example { char c; int ii; int iii; };
int main(int argc, char *argv[])
{
    printf("offsetof(struct example, c) == %zd\n", offsetof(struct example, c));
    printf("offsetof(struct example, ii) == %zd\n", offsetof(struct example, ii));
    printf("offsetof(struct example, iii) == %zd\n", offsetof(struct example, iii));
    return 0;
}
请注意,
sizeof(char)==1
,但在
ii
字段之前有四个字节。额外的三个字节是填充。存在填充以确保数据类型排列在处理器的正确边界上

如果处理器进行未对齐的访问,可能会发生各种情况:

  • 访问速度较慢(大多数x86)
  • 访问必须由内核处理,速度非常慢(各种PowerPC)(这导致一些计算机游戏在速度较快的PPC603处理器上运行非常慢,而在速度较慢的PPC601处理器上运行得很好。)
  • 程序崩溃(各种SPARC)

我知道填充物没有已知的风险。真正发生的唯一问题是,使用不同编译器编译的两个程序(已知GCC和MSVC会导致这种情况)使用不同的填充,并且不能共享结构。如果来自不同编译器的代码链接在一起,这也会导致崩溃。由于填充通常由平台ABI指定,因此这种情况很少出现。

为什么不编译一些代码并进行测试?填充取决于编译器和体系结构。例如,一个风险是按原样通过网络发送结构-因为在声明
struct
变量时,另一端的填充可能不同,因此必须在typename之前使用
struct
关键字。你是真的使用C++还是仅仅从C++学习C并且有一些习惯?@ DRAKOSHA:连数和大小也不同。直接序列化任意结构从来都不安全。@Dietrich Epp:当然,谢谢!为什么不编译一些代码并进行测试呢?填充取决于编译器和体系结构。例如,一个风险是按原样通过网络发送结构-因为在声明
struct
变量时,另一端的填充可能不同,因此必须在typename之前使用
struct
关键字。你是真的使用C++还是仅仅从C++学习C并且有一些习惯?@ DRAKOSHA:连数和大小也不同。直接序列化任意结构从来都不安全。@Dietrich Epp:当然,谢谢!填充的一个风险是,新手程序员使用结构来格式化通过网络发送到另一台机器的二进制数据。假设这个结构包含一些缓冲区长度信息,那么剩下的就由你来计算。这不是填充的问题,这是不检查缓冲区大小的问题。如果不检查缓冲区大小,则无论填充是否不同,都会出现缓冲区溢出。填充的一个风险是,新手编码器使用结构来格式化通过网络发送到另一台机器的二进制数据。假设这个结构包含一些缓冲区长度信息,那么剩下的就由你来计算。这不是填充的问题,这是不检查缓冲区大小的问题。如果不检查缓冲区大小,则无论填充是否不同,都会出现缓冲区溢出。