You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于调整结构体成员顺序缩减结构体大小的原理疑问

结构体成员顺序对内存对齐与大小的影响

我正在学习数据对齐相关内容,了解结构体成员顺序对结构体大小的影响。相关内容提到:

结构体内部所有数据均自然对齐。若type位于地址0,后续的double x将位于偏移量8的地址8处,依此类推。因此该结构体大小为48字节,尽管仅包含37字节有效数据。并且,若float m紧跟在type之后,m的偏移量将为4,结构体大小会缩减至40字节。

我有个疑问:为什么仅仅改变成员顺序就能把结构体大小从48字节缩减到40字节?是不是因为原顺序中double vy的偏移量是40,之后需要额外填充8字节让结构体大小满足对齐要求到48;而调整顺序后double vy的偏移量是32,填充8字节后大小就到40了?

我编写了一个C程序验证结构体成员的对齐情况:

/*Outputs:
particle one alignment:
type 0
x 8
y 16
m 24
vx 32
vy 40
struct size --> 48
particle two alignment:
type 0
m 4
x 8
y 16
vx 24
vy 32
struct size --> 40
*/
#include <stdio.h>                                                                           
#include <stdlib.h>                                                                          
                                                                                             
typedef struct ParticleOne {                                                                 
    char type;                                                                               
    double x,y;                                                                              
    float m;         // after `y` member                                                                        
    double vx, vy;                                                                           
} ParticleOne;                                                                               
                                                                                             
typedef struct ParticleTwo {                                                                 
    char type;                                                                               
    float m;         // after `type` member                                                                        
    double x,y;                                                                              
    double vx, vy;                                                                           
} ParticleTwo;                                                                               
                                                                                             
int main() {                                                                                 
    ParticleOne *particle_one = malloc(sizeof(ParticleOne));                                  
    ParticleTwo *particle_two = malloc(sizeof(ParticleTwo));                                  
                                                                                             
    // Particle one alignment/offset information                                                                          
    void *p1_type = &particle_one->type;                                                      
    void *p1_x = (void*)&particle_one->x - p1_type;                                           
    void *p1_y = (void*)&particle_one->y - p1_type;                                           
    void *p1_m = (void*)&particle_one->m - p1_type;                                           
    void *p1_vx = (void*)&particle_one->vx - p1_type;
    void *p1_vy = (void*)&particle_one->vy - p1_type;

    printf("particle one alignment:\n");
    printf("type %d\n", p1_type - p1_type);
    printf("x %d\n", p1_x);
    printf("y %d\n", p1_y);
    printf("m %d\n", p1_m);
    printf("vx %d\n", p1_vx);
    printf("vy %d\n", p1_vy);
    printf("struct size --> %d\n", sizeof(ParticleOne));    

    // Particle two alignment/offset information
    void *p2_type = &particle_two->type;
    void *p2_x = (void*)&particle_two->x - p2_type;
    void *p2_y = (void*)&particle_two->y - p2_type;
    void *p2_m = (void*)&particle_two->m - p2_type;
    void *p2_vx = (void*)&particle_two->vx - p2_type;
    void *p2_vy = (void*)&particle_two->vy - p2_type;

    printf("particle two alignment:\n");
    printf("type %d\n", p2_type - p2_type);
    printf("m %d\n", p2_m);
    printf("x %d\n", p2_x);
    printf("y %d\n", p2_y);
    printf("vx %d\n", p2_vx);
    printf("vy %d\n", p2_vy);
    printf("struct size --> %d\n", sizeof(ParticleTwo));

    return 0;
}

你的猜测完全正确,核心原因就是内存对齐规则:

  1. 结构体的每个成员都要满足自身的自然对齐要求:char占1字节(无需额外对齐),float占4字节(需对齐到4字节边界),double占8字节(需对齐到8字节边界)。
  2. 结构体整体的大小必须是其最大成员对齐字节数的整数倍(这里最大成员是double,即8字节)。

原结构体(ParticleOne)的内存布局:

  • char type:占0-0字节,之后需要填充7字节(因为下一个成员double x要对齐到8字节边界),所以x从8字节开始。
  • double x:8-15字节;double y:16-23字节。
  • float m:24-27字节(占4字节),之后需要填充4字节(下一个成员double vx要对齐到8字节边界),所以vx从32字节开始。
  • double vx:32-39字节;double vy:40-47字节。
  • 结构体整体大小是48字节,正好是8的整数倍,无需额外填充。

调整顺序后的结构体(ParticleTwo)的内存布局:

  • char type:0-0字节,之后填充3字节(下一个成员float m要对齐到4字节边界),m从4字节开始。
  • float m:4-7字节,下一个成员double x要对齐到8字节边界,刚好从8字节开始,无需填充。
  • double x:8-15字节;double y:16-23字节;double vx:24-31字节;double vy:32-39字节。
  • 结构体整体大小是40字节,正好是8的整数倍,无需额外填充。

简单来说,调整顺序后,把小尺寸的float m放在char type后面,利用了type后面的填充空间(原本要填7字节,现在填3字节给m用),避免了后续double成员前的额外填充,最终减少了整体的内存占用。

内容的提问来源于Stack Exchange,提问作者Jared

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 18:05:39