只有一个元素的结构体大小

18

假设有

struct S {
  SomeType single_element_in_the_struct;
};

它总是正确的吗?

sizeof(struct S) == sizeof(SomeType)

或者这可能取决于具体的实现?

3个回答

14

通常情况下是这样的,但不能保证。

任何结构体都可能在其末尾有未命名填充字节(unnamed padding bytes),但这些通常用于对齐目的。如果只有一个元素,则这不是一个问题。


3
如果您只有一个元素,这不是一个问题。实际上,出于对齐和性能的考虑,在结构体中处理单个元素仍可能存在填充。例如,在32位系统上使用char array[6]时,可能会填充2个额外字节以成为4字节(32位)的整数倍。 - mctylr
1
@mctylr:如果这种行为是典型的,我会有点惊讶。数组元素之间不能有填充,因此char [6]的大小为六个字节,而char [6] [2]的大小为12个字节。我不认为与其包含的类型char [6]对齐的类型struct S { char c [6]; };的益处在于此。 - James McNellis
1
我是指将其视为 struct S = {char array[6]; char pad[2];}。由于32位CPU无论如何都会访问8个字节,如果struct S本身在第二个数组struct S aS[]中,则数组的元素将对齐到对齐边界上。我不认为这很常见,但有可能发生。我曾经看到人们在直接通过fwrite / write将结构体写入二进制文件或网络套接字时假设没有这样的填充,这可能会导致错误。 - mctylr
附加情况:考虑一个字寻址的机器,其中sizeof(char*) > sizeof(int*)。(char指针必须有额外的位来选择一个字。)标准保证所有指向结构体的指针具有相同的大小,因此结构体通常始终是字对齐的(您可以选择说所有结构体指针都不对齐,但在这种机器上通常不是这样选择的)。如果所有结构体是字对齐的,则sizeof(struct S { char a;})将大于sizeof(char)。 - Martin Bonner supports Monica

13

由于结构体填充,大小不一定相等。

C99标准的第6.7.2.1节规定:“结构体对象内可能存在无名填充,但在其开头不能有填充。”

这被称为结构体填充。为了确保结构体在内存中正确对齐,可能会添加填充。如果更改结构体成员的顺序,结构体的确切大小可能会发生变化。


1
或者,两段之后,“结构体或联合体的末尾可能存在未命名填充”。 - James McNellis
这并不是特别有用,因为OP标记了C++和C两种语言。 - Puppy
3
如果结构体中只有一个成员,填充是否起作用呢?这是OP的问题,到目前为止我在n1256中没有找到明确的答案。例如,根据gcc的规定,包含一个只有三个元素的char数组的单一结构体的大小为3;没有填充。在数组后添加一个int,数组的大小变为8,因此元素之间有一个字节的填充。 - John Bode

1

这取决于编译器的打包方式。通常,结构的大小可被系统的字长整除(例如,4字节==32位)。

因此,您经常会有 sizeof(struct S) > sizeof(SomeType)

对于大多数编译器,您可以使用编译器指示修改打包大小。 如果您设置 #pragma pack(1) 那么大小应该相等。


1
通常情况下,它不依赖于打包。结构的对齐通常被计算为结构成员的最强对齐方式。如果所有成员都是字符,则在大多数情况下对齐将为1(无论默认打包如何)。 - user396672

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接