0

Padding trong struct

Xem ví dụ sau đây: Viết một struct message_t đơn giản để quản lí các thông tin và dữ liệu của message

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>


typedef struct {
    uint8_t event_id;
    uint8_t sender_id;
    void*   payload;       // con trỏ tới vùng nhớ ngay sau struct
    uint8_t size_payload;
} Message_t;

Message_t* Message_Create(uint8_t event, uint8_t sender, const char* str) {
    size_t len = strlen(str) + 1; // +1 để chứa cả ký tự null terminator

    // Cấp phát chung: struct + payload
    Message_t* newMessage = (Message_t*)malloc(sizeof(Message_t) + len);
    if (newMessage == NULL) return NULL;

    newMessage->event_id     = event;
    newMessage->sender_id    = sender;
    newMessage->size_payload = (uint8_t)len;

    // payload nằm ngay sau struct
    newMessage->payload = (uint8_t*)newMessage + sizeof(Message_t);

    memcpy(newMessage->payload, str, len);

    return newMessage;
}

void Message_Free(Message_t* msg) {
    free(msg); // chỉ cần free 1 lần
}

int main() {
    Message_t* msg = Message_Create(1, 42, "Hello OS!");
    
    printf("dia chi bat dau message_t:  %p\n", msg);
    printf("dia chi cua event_id:       %p\n", &msg->event_id);
    printf("dia chi cua sender_id:      %p\n", &msg->sender_id);
    printf("dia chi cua payload:        %p\n", &msg->payload);
    printf("dia chi cua size_payload:   %p\n", &msg->size_payload);
    
    printf("dia chi bat dau du lieu:    %p\n", msg->payload);
    
    
    Message_Free(msg);
    return 0;
}

Output

dia chi bat dau message_t:  0x55752a7582a0
dia chi cua event_id:       0x55752a7582a0
dia chi cua sender_id:      0x55752a7582a1
dia chi cua payload:        0x55752a7582a8
dia chi cua size_payload:   0x55752a7582b0
dia chi bat dau du lieu:    0x55752a7582b8

Ta thấy được việc chưa tối ưu về vị trí các trường trong struct sẽ làm lãng phí bộ nhớ.

Theo như sắp xêp như trên

  • event_id: chiếm 1 byte
  • sender_id: chiếm 1 byte
  • padding: 6 byte
  • payload: 8 byte
  • size_payload: 1 byte
  • padding: 7 byte

=> Tổng cộng: 24 byte.

Nhưng nếu bây giờ ta sắp xếp lại thứ tự các trường trong struct như sau:

typedef struct {
    uint8_t event_id;
    uint8_t sender_id;
    uint8_t size_payload;
    void*   payload;
} Message_t;
  • event_id: 1 byte
  • sender_id: 1 byte
  • size_payload: 1 byte
  • padding: 5 byte
  • payload: 8 byte

-> Tổng cộng: 16 byte, tiết kiệm được 8 byte.

Rút ra kết luận: Việc sắp xếp thứ tự các trường trong struct rất quan trọng trong việc tiết kiệm bộ nhớ và vẫn đảm bảo hiệu năng.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí