西西55 发表于 2024-1-2 18:26:45

字节对齐

1.struct A
      {
                int a;
                char b;
                short c;
      };sizeof(A)是多少?

2.struct A
      {
                int a;
                char b【10】;
                short c;
      };sizeof(A)是多少?4+12=16?









FishC 发表于 2024-1-2 18:26:56

1. 首先,我们需要了解字节对齐的概念。字节对齐是指在内存中存储数据时,变量的起始地址必须是其类型大小的整数倍。这是为了提高内存读取的效率。

对于第一个结构体A来说,int类型占4个字节,char类型占1个字节,short类型占2个字节。按照字节对齐的原则,int类型的起始地址是4的倍数,char类型的起始地址是1的倍数,short类型的起始地址是2的倍数。所以,为了满足字节对齐的要求,编译器会在char类型后面填充3个字节,将short类型的起始地址对齐。因此,结构体A的大小为4 + 1 + 3 + 2 = 10个字节。

所以,sizeof(A)的结果是10。

2. 对于第二个结构体A来说,int类型占4个字节,char类型占10个字节,short类型占2个字节。按照字节对齐的原则,int类型的起始地址是4的倍数,char类型的起始地址是1的倍数,short类型的起始地址是2的倍数。所以,为了满足字节对齐的要求,编译器会在char类型后面填充2个字节,将short类型的起始地址对齐。因此,结构体A的大小为4 + 10 + 2 = 16个字节。

所以,sizeof(A)的结果是16。

希望这个解答能够帮到你!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

jackz007 发表于 2024-1-2 20:22:35

本帖最后由 jackz007 于 2024-1-2 21:26 编辑

#include <stdio.h>

int main(void)
{
      struct A {
            inta   ; // a 从偏移 0 的位置开始,正常占用 4 个字节
            char b   ; // b 从偏移为 4 的位置开始,占用 1 个字节
            short c    ; // c 本应从偏移 5 的位置开始,但是,由于 c 占用 2 个字节,必须从 2 的整数倍偏移位置开始,所以,c 从偏移为 6 的位置开始,占用 2 个字节
      }            ; // struct A 一共需要占用 8 个字节
      struct B {
            int a      ; // a 从偏移 0 的位置开始,正常占用 4 个字节
            char b ; // b 从偏移为 4 的位置开始,占用 10 个字节
            short c    ; // c 从偏移为 14 的位置开始,占用 2 个字节               
      }            ; // struct B 一共需要占用 16 个字节      
      printf("the sizeof(struct A) is %d\n" , sizeof(struct A)) ;
      printf("the sizeof(struct B) is %d\n" , sizeof(struct B)) ;      
}
      更加有意思的是,一模一样的两个结构,仅仅因为成员顺序不同,从而导致占用空间存在较大差异:
#include <stdio.h>

int main(void)
{
      struct A {
            char a          ; // a 从偏移 0 的位置开始,正常占用 1 个字节
            long long b   ; // b 本应从偏移为 1 的位置开始,由于 b 需要占用 8 个字节,需要从 8 字节对齐的位置开始,所以,b 从偏移 8 开始,占用 8 个字节
            short c         ; // c 从偏移为 16 的位置开始,占用 2 个字节
            int d         ; // d 本应从偏移为 18 的位置开始,但是,由于 d 占用 4 个字节,需要从 4 字节对齐的位置开始,所以,d 从偏移 20 开始,占用 4 个字节
      }                   ; // struct A 一共需要占用 24 个字节

      struct B {
            char a          ; // a 从偏移为 0 的位置开始,正常占用 1 个字节
            short c         ; // c 本应从偏移为 1 的位置开始,由于 c 需要占用 2 个字节,需要从 2 字节对齐的位置开始,所以,c 从偏移 2 开始,占用 2 个字节
            int d         ; // d 从偏移为 4 的位置开始,占用 4 个字节
            long long b   ; // b 从偏移为 8 的位置开始,占用 8 个字节
      }                   ; // struct B 一共需要占用 16 个字节      
      printf("the sizeof(struct A) is %d\n" , sizeof(struct A)) ;
      printf("the sizeof(struct B) is %d\n" , sizeof(struct B)) ;
}
      而所有这一切,都是因为边界对齐所致。

liyifeng295641 发表于 2024-1-3 20:17:11

jackz007 发表于 2024-1-2 20:22
更加有意思的是,一模一样的两个结构,仅仅因为成员顺序不同,从而导致占用空间存在较大差异:
...

你是al吗?

jackz007 发表于 2024-1-3 21:51:51

liyifeng295641 发表于 2024-1-3 20:17
你是al吗?

      不是,我是活人!

liyifeng295641 发表于 2024-1-3 21:52:55

jackz007 发表于 2024-1-3 21:51
不是,我是活人!

{:10_257:}

jackz007 发表于 2024-1-3 21:53:46

liyifeng295641 发表于 2024-1-3 21:52


      能看明白我的解释吗?

liyifeng295641 发表于 2024-1-3 21:54:46

jackz007 发表于 2024-1-3 21:53
能看明白我的解释吗?

不能的

jackz007 发表于 2024-1-3 21:55:51

liyifeng295641 发表于 2024-1-3 21:54
不能的

      哪里看不懂?

liyifeng295641 发表于 2024-1-3 21:59:17

jackz007 发表于 2024-1-3 21:55
哪里看不懂?

偏移,

jackz007 发表于 2024-1-3 22:19:23

本帖最后由 jackz007 于 2024-1-4 08:21 编辑

liyifeng295641 发表于 2024-1-3 21:59
偏移,

       其实,很容易理解,你可以把结构体视为一把有刻度的尺子,结构体开始位置的刻度为 0,刻度的单位为字节,你还可以把结构体的成员想象为有长度的线段,例如,int 型成员占用 4 个字节,那么,它就是一条长度为 4 的线段,所有的成员需要按照各自在结构体中的先后顺序在这把“尺子”上“排队”,而且,彼此互不重叠。例如,有个结构体,有 a、b、c 三个 int 型的成员,则它们会彼此首尾相接,以 a、b、c 的先后顺序,无缝拼接成为一条长度为 12 的线段,如果用尺子来衡量,则 a、b、c 分别开始于 0、4、8,这就是我们所说的偏移。
       假如,又有一个结构体,有 a、b 两个成员,其中,成员 a 是 char 型,长度为 1 ,那么,它会占据刻度 0~1,第二个成员 b
是 long long 型,其长度为 8,本应占据刻度 1~9,但是,按照字节边界对齐的规则,其开始位置必须是 8 的倍数,于是,成员 b 便实际占用了刻度 8~16,这样,由于字节边界对齐的原因,成员 a 和 b 未能首尾相接,而是以间断的状态占据了尺子 0~16 的刻度区间,其中,在1~8 的刻度位置是一个“缺口”。
页: [1]
查看完整版本: 字节对齐