Quản lý kích thước bộ nhớ đối với Struct trong C/C++

Khi ta khai báo một struct thì nó sẽ được cấp phát tự động một vùng nhớ có độ dài mà ta khó có thể biết chính xác. Ở phần lớn các bài toán ta không cần quan tâm xem struct mà mình khai báo sẽ được cấp phát như thế nào và nó được cấp bao nhiêu byte. Tuy nhiên ở một vài bài toán đặc thù thì ta phải kiểm soát, biết chắc chắn struct mà mình khai báo sẽ được cấp phát như thế nào. Trong struct sẽ cung cấp cho ta một số thuộc tính để làm việc này.

1: attribute aligned
Trong bài toán liên quan đến các protocol khi mà định dạng gói tin được chỉ rõ: có bao nhiêu field, độ dài các field là bao nhiêu, … Vì vậy để chương trình có thể chạy đúng protocol thì khi coder khai báo struct để biểu diễn các field đó phải làm sao đó để chắc chắn struct mà mình khai báo sẽ có độ dài đúng bằng độ dài mà protocol đó định nghĩa.

Khai báo:

struct Aligned_t  
 {  
      char cdata;  
      int idata;  
      float fdata;  
 }__attribute__ ((aligned (8)));

Thuộc tính aligned(n) dùng để cho biết struct sẽ được cấp vùng nhớ có độ dài
sizeof struct = n*x, trong đó n là số byte để aligne, giá trị n = 2^m, tức là bằng cấp số mũ của 2; x là số nguyên dương với điều kiện x >= 1. Ví dụ trên n = 8, vì vậy biến kiểu struct Aligned_t sẽ được cấp vùng nhớ có độ dài là cấp số nhân của 8.

2: attribute((packed))
Dùng để minimum độ dài vùng nhớ của struct, mục đích tiết kiệm bộ nhớ.
Khai báo:

 struct Packed_t  
 {  
      char cdata; //1  
      int idata; //4  
      float fdata; //4  
 }__attribute__((packed));// == minimum ==> 9  

Ví dụ:
attribute.c

 #include <stdio.h>  
   
   
 struct Normal_t  
 {  
      char cdata; //4  
      int idata; //4  
      float fdata; //4  
 };// 12  
   
 struct Aligned_t  
 {  
      char cdata;  
      int idata;  
      float fdata;  
 }__attribute__ ((aligned (8))); // 12 == align 8 ==> 16  
   
 struct Packed_t  
 {  
      char cdata; //1  
      int idata; //4  
      float fdata; //4  
 }__attribute__((packed));// == minimum ==> 9  
   
    
 int main(int argc, char **argv)  
 {  
      printf("sizeof(char): %d\n", (int)sizeof(char));  
      printf("sizeof(int): %d\n", (int)sizeof(int));  
      printf("sizeof(float): %d\n", (int)sizeof(float));  
      printf("sizeof(long): %d\n", (int)sizeof(long));  
      printf("\n\n");  
   
      struct Normal_t m1;  
      struct Aligned_t m2;  
      struct Packed_t m3;  
   
      printf("sizeof(Normal_t): %d\n", (int)sizeof(m1));  
      printf("sizeof(Aligned_t): %d\n", (int)sizeof(m2));  
      printf("sizeof(Packed_t): %d\n", (int)sizeof(m3));  
   
      return 0;  
 }  

Compile & Execute

$ gcc attribute.c   
 $ ./a.out   
 sizeof(char): 1  
 sizeof(int): 4  
 sizeof(float): 4  
 sizeof(long): 8  
   
   
 sizeof(Normal_t): 12  
 sizeof(Aligned_t): 16  
 sizeof(Packed_t): 9
5 Likes

mấy cái này rất hay gặp trong lập trình nhúng, xin hỏi bác đang công tác ở đâu ạ ?

Mình củng mới bắt đầu học về Embedded thôi bạn, nếu bạn củng theo mảng này thì cùng nhau học hỏi hi. Mình củng chưa có kiến thức nhiều về EBD nên lên diễn dàn cùng nhau thảo luận để học hỏi.

1 Like

Bác có thể giải thích giúp em vì sao khi thêm hàm virtual vào struct thì khiển size của nó tăng thêm 8 bit không ạ.

Vì 8 byte là kích thước một con trỏ. virtual cần phải có địa chỉ hàm để gọi cho đúng.

p/s: 8 byte nhé.

1 Like
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?