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
Let's register a Viblo Account to get more interesting posts.