C中结构的实际大小是多少

C中结构的实际大小是多少,c,gcc,ubuntu,C,Gcc,Ubuntu,可能重复: 以下是在Ubuntu Server 11.10上为i386机器编译的代码: // sizeof.c #include <stdio.h> #include <malloc.h> int main(int argc, char** argv){ printf("int's size: %d bytes\n", sizeof(int)); printf("double's size: %d bytes\n", sizeof(

可能重复:

以下是在Ubuntu Server 11.10上为i386机器编译的代码:

// sizeof.c
#include <stdio.h>
#include <malloc.h>


int main(int argc, char** argv){
        printf("int's size: %d bytes\n", sizeof(int));
        printf("double's size: %d bytes\n", sizeof(double));
        printf("char's size: %d bytes\n", sizeof(char));
        printf("\n");

        printf("char pointer's size: %d\n", sizeof(char *));
        printf("\n");

        struct Stu{
                int id;
                char* name;
                char grade;
                char sex;
        //      double score;
        };
        printf("struct Stu's pointer's size : %d\n",sizeof(struct Stu *));

        struct Stu stu;
        stu.id=5;
        stu.name="Archer";
        stu.grade='A';
        stu.sex='M';
        printf("Stu(int,char*, char,char)'s size: %d bytes\n", sizeof(struct Stu));
        printf("Stu(5,\"Archer\",'A','M')'s size: %d bytes\n",sizeof(stu));
}
输出:

int's size: 4 bytes
double's size: 8 bytes
char's size: 1 bytes

char pointer's size: 4

struct Stu's pointer's size : 4
Stu(int,char*, char,char)'s size: 12 bytes
Stu(5,"Archer",'A','M')'s size: 12 bytes

我的问题是为什么
struct Stu
的大小是12,而不是
sizeof(int)+sizeof(char*)+sizeof(char)+sizeof(char)=4+4+1+1=10。将双成员放入
struct Stu
,则
sizeof(struct Stu)`将为20

要计算用户定义类型的大小,编译器将考虑复杂用户定义数据结构所需的任何对齐空间。这就是C中结构的大小可以大于其成员大小之和的原因。例如,在许多系统上,以下代码将打印8:

提及

假设您具有以下结构:

struct A1
{
  char a[2];
  int b;
};
你可以认为sizeof(A1)等于6,但事实并非如此。等于8。编译器在成员“a”和“b”之间插入2个伪字节

原因是编译器会将成员变量与包大小的倍数或类型大小的倍数对齐,以最小者为准

visual studio中的默认包大小为8字节

“b”是整数类型,宽4字节b'将与这2个字节中的最小值对齐,即4个字节。“a”是1、2、3还是4字节宽都无关紧要b'将始终在同一地址上对齐


referen

数据必须正确对齐才能获得良好的效率,因此编译器可以自由地在结构内部添加填充(除了开始处以外的任何位置)

通常,N字节类型(用于1、2、4、8、16字节)在N字节地址边界上对齐

因此,对于32位编译,结构具有:

    int id;          // offset =  0, size = 4
    char* name;      // offset =  4, size = 4
    char grade;      // offset =  8, size = 1
    char sex;        // offset =  9, size = 1
    double score;    // offset = 16, size = 8
总共24号。请注意,即使将
double
移动到结构的前面或名称后面,大小仍将为24,因为结构数组的所有元素都必须正确对齐,因此将至少有6个字节填充。(有时,double只需要在4字节边界上对齐;然后填充将是2字节而不是6字节。)

即使没有
double
成员,结构也必须有12个字节长,这样
id
就可以为数组中的额外元素正确对齐-将有2个字节的填充


一些编译器为程序员提供了一条名为
#pragma pack
的绳子或类似的绳子,一些程序员抓住机会,用这样提供的绳子将自己吊死。

填充以对齐对齐边界上的数据成员。可能重复,,,这些注释是正确的,答案(到目前为止)很差@数学的答案与这个问题无关@科迪的评论是绝对正确的,正如@Mysticial的参考文献albiet更加简洁。通常有一些编译器杂注会迫使结构压缩到最小的空间中,但除非您使用这些杂注,否则编译器会优化字级访问(甚至是CPU字大小的倍数),因此每个
char
都在自己的字中,通常是一个4字节的块。@Cyberfox:Yes,答案很差,因为这个问题是重复的。这里的标准做法是不在多个地方重复答案。为什么否定性是w.r.t.
#pragma pack
?:)如果您处理的是磁盘上或网络上的数据表示,这几乎是必不可少的。因为这会使程序运行速度变慢,并且需要小心确保pragma的使用一致。总的来说,至少就我所做的工作而言,确保结构布局尽可能紧凑并带有任何填充比以额外的时间访问结构中未对齐的数据为代价从系统中挤出最大的空间更简单/更好。我从未发现有必要使用
#pragma pack
;我不希望这样做。但是我用C语言编写代码才四分之一个世纪(而且只在有限的程序范围内),所以这可能对其他人很重要。我想,只要在相同的目标体系结构上使用相同版本的相同编译器,就不会出现问题。当您向具有不同内存字大小和未对齐访问规则的计算机发送数据时,您会怎么做?我正确地序列化了。我一直在处理SPARC(big-endian)、PPC(同上)和Intel(little-endian)之间的数据。这涉及到一些工作,但仅在发送数据时,而不是在数据到达后(或准备发送之前)访问结构时<代码>#pragma pack对这些机器没有帮助;它是不可移植的,并且不需要在不同机器上的不同编译器(甚至在一台机器上的不同编译器)上执行相同的操作。
#pragma pack
在构建嵌入式处理器的C模拟时是强制性的,该嵌入式处理器具有针对像素值和辅助信息的打包输出格式。这大概是我唯一一次使用打包pragma来模拟特定的硬件输出。我同意应该避免,除非你处于相当可怕/特殊的情况。
    int id;          // offset =  0, size = 4
    char* name;      // offset =  4, size = 4
    char grade;      // offset =  8, size = 1
    char sex;        // offset =  9, size = 1
    double score;    // offset = 16, size = 8