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