关于结构体字节对齐的问题

soundbird 2016-12-29 04:21:01
最近任务完成后,又重新捡起一些基础书籍看看,弥补一下自己的基础知识,就遇到一个问题,这里问问明白人。
看到字节对齐的时候,就自己写几个测试,结果大跌眼镜:

struct test1 {
char text[2];
long number1;
long long number2;
};
int nsize = sizeof(test1);

结构体test1的大小很好理解,根据字节对齐的理论,针对char,系统自动填充2个字节,long大小是4,long long的大小是8,所以test1的大小为16,运行结果跟我设想一致。但是接下来的我就不理解了

struct test2 {
char text[5];
long number1;
long long number2;
};
int nsize = sizeof(test1);


struct test3 {
char text[2];
long long number2;
long number1;
};
int nsize = sizeof(test1);

结构体test2和test3的大小都是24,请问,为什么两个结构体大小都为24?
...全文
622 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
Eleven 2017-01-11
  • 打赏
  • 举报
回复
struct test2 {
           char text[5];
           long number1;
           long long number2;
};

text占0,1,2,3,4五个字节,下一个成员就从5开始,但是起始地址值需要是长度long number1的整数倍,所以需填充5~7三个字节,所以从8开始,number1就占了8~11这四个字节,下一个long long number2就从12开始,但是起始地址值需要是长度的整数倍,所以需填充12_15这四个字节,所以最后一个成员number2就从16开始,即16~23这八个字节的长度,因此是24字节的大小,24是最大成员number2的长度的整数倍,所以最后结构体的sizeof就是24.

struct test3 {
           char text[2];
           long long number2;
           long number1;
};

text占0,1两个字节,下一个从2开始,但是起始地址值需要是长度long long number2的整数倍,所以需填充2~7六个字节,所以从8开始,number2就占了8~15这八个字节,下一个long number1就从16开始,即16~19这四个字节的长度,因此是20字节的大小。但是最终结构体的sizeof值必须是最大成员number2长度整数倍,所以最后需要填充20~23四个字节,即最后结构体的sizeof就是24.
  • 打赏
  • 举报
回复
引用 9 楼 VisualEleven 的回复:
struct test2 {
           char text[5];
           long number1;
           long long number2;
};
text占0,1,2,3,4五个字节,下一个成员就从5开始,但是起始地址值需要是长度long number1的整数倍,所以需填充5~7三个字节,所以从8开始,number1就占了8~11这四个字节,下一个long long number2就从12开始,但是起始地址值需要是长度的整数倍,所以需填充12_15这四个字节,所以最后一个成员number2就从16开始,即16~23这八个字节的长度,因此是24字节的大小,24是最大成员number2的长度的整数倍,所以最后结构体的sizeof就是24.
struct test3 {
           char text[2];
           long long number2;
           long number1;
};
text占0,1两个字节,下一个从2开始,但是起始地址值需要是长度long long number2的整数倍,所以需填充2~7六个字节,所以从8开始,number2就占了8~15这八个字节,下一个long number1就从16开始,即16~19这四个字节的长度,因此是20字节的大小。但是最终结构体的sizeof值必须是最大成员number2长度整数倍,所以最后需要填充20~23四个字节,即最后结构体的sizeof就是24.
darknoll 2017-01-10
  • 打赏
  • 举报
回复
size = 最后一个元素的偏移地址+当前长度+对齐长度
zgl7903 2017-01-10
  • 打赏
  • 举报
回复
VC编译器默认的的结构体对齐是Z8(8字节) 可以用 #pragma pack 定义结构体对齐字节数 #pragma pack(push, 1) //1字节对齐 #pragma pack(pop)
Pingo520 2017-01-10
  • 打赏
  • 举报
回复
4楼正解
赵4老师 2017-01-03
  • 打赏
  • 举报
回复
仅供参考:
#include <stdio.h>
#define field_offset(s,f) (int)(&(((struct s *)(0))->f))
struct AD  { int a; char b[13]; double c;};
#pragma pack(push)
#pragma pack(1)
struct A1  { int a; char b[13]; double c;};
#pragma pack(2)
struct A2  { int a; char b[13]; double c;};
#pragma pack(4)
struct A4  { int a; char b[13]; double c;};
#pragma pack(8)
struct A8  { int a; char b[13]; double c;};
#pragma pack(16)
struct A16 { int a; char b[13]; double c;};
#pragma pack(pop)
int main() {
    printf("AD.a %d\n",field_offset(AD,a));
    printf("AD.b %d\n",field_offset(AD,b));
    printf("AD.c %d\n",field_offset(AD,c));
    printf("AD sizeof %d\n", sizeof(AD));
    printf("\n");
    printf("A1.a %d\n",field_offset(A1,a));
    printf("A1.b %d\n",field_offset(A1,b));
    printf("A1.c %d\n",field_offset(A1,c));
    printf("A1 sizeof %d\n", sizeof(A1));
    printf("\n");
    printf("A2.a %d\n",field_offset(A2,a));
    printf("A2.b %d\n",field_offset(A2,b));
    printf("A2.c %d\n",field_offset(A2,c));
    printf("A2 sizeof %d\n", sizeof(A2));
    printf("\n");
    printf("A4.a %d\n",field_offset(A4,a));
    printf("A4.b %d\n",field_offset(A4,b));
    printf("A4.c %d\n",field_offset(A4,c));
    printf("A4 sizeof %d\n", sizeof(A4));
    printf("\n");
    printf("A8.a %d\n",field_offset(A8,a));
    printf("A8.b %d\n",field_offset(A8,b));
    printf("A8.c %d\n",field_offset(A8,c));
    printf("A8 sizeof %d\n", sizeof(A8));
    printf("\n");
    printf("A16.a %d\n",field_offset(A16,a));
    printf("A16.b %d\n",field_offset(A16,b));
    printf("A16.c %d\n",field_offset(A16,c));
    printf("A16 sizeof %d\n", sizeof(A16));
    printf("\n");
    return 0;
}
//AD.a 0
//AD.b 4
//AD.c 24
//AD sizeof 32
//
//A1.a 0
//A1.b 4
//A1.c 17
//A1 sizeof 25
//
//A2.a 0
//A2.b 4
//A2.c 18
//A2 sizeof 26
//
//A4.a 0
//A4.b 4
//A4.c 20
//A4 sizeof 28
//
//A8.a 0
//A8.b 4
//A8.c 24
//A8 sizeof 32
//
//A16.a 0
//A16.b 4
//A16.c 24
//A16 sizeof 32
//
//
  • 打赏
  • 举报
回复
引用 2 楼 soundbird 的回复:
[quote=引用 1 楼 akirya 的回复:] 元素的起始地址是sizeof(元素类型)的整数倍,结构体大小是最大元素的整数倍。 所以 test2 text 5字节, 空3字节 number1 4字节,空4字节 number2 8字节 test3 text 2字节,空6字节 number2 8字节 number1 4字节,空4字节
那按照这个说,结构test1也应该是24,那为什么是16,就这点不懂[/quote] test1 就是你说的啊。
soundbird 2016-12-30
  • 打赏
  • 举报
回复
引用 1 楼 akirya 的回复:
元素的起始地址是sizeof(元素类型)的整数倍,结构体大小是最大元素的整数倍。 所以 test2 text 5字节, 空3字节 number1 4字节,空4字节 number2 8字节 test3 text 2字节,空6字节 number2 8字节 number1 4字节,空4字节
那按照这个说,结构test1也应该是24,那为什么是16,就这点不懂
compass233 2016-12-30
  • 打赏
  • 举报
回复
test1 里 2 + 4 = 6 再补2个字节就对齐到8字节,所以是 8 + 8 = 16 test2 里 5 + 4 = 9 大于8字节,只能分别对齐到8字节,所以是 8 + 8 + 8 = 24
  • 打赏
  • 举报
回复
元素的起始地址是sizeof(元素类型)的整数倍,结构体大小是最大元素的整数倍。 所以 test2 text 5字节, 空3字节 number1 4字节,空4字节 number2 8字节 test3 text 2字节,空6字节 number2 8字节 number1 4字节,空4字节

16,470

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧