Struct

Struct

Struct là một nhóm của các thành viên, mỗi thành viên có một kiểu dữ liệu khác nhau.
Ví dụ ta mô tả sản phẩm với các thuộc tính là cân nặng và giá.

1
2
3
4
5
6
struct Product {
  int weight; 
  double price;
};
// khai báo hai sản phẩm product1, product2
struct Product product1, product2;

Struct với typedef

Để bỏ với từ khóa struct khi mô tả struct chúng ta nên sử dụng từ khóa typedef.

1
2
3
4
5
6
7
8
struct Product {
  int weight; 
  double price;
};
typedef struct Product Product;

// khai báo hai sản phẩm product1, product2 (không có từ khóa struct)
Product product1, product2;

hoặc sử dụng cách viết ngắn gọn với typedef

1
2
3
4
typedef struct Product {
  int weight; 
  double price;
} Product;

Khởi tạo và gán giá trị cho struct

Từ chuẩn C99, chúng ta có thể khai báo và gán ngay giá trị cho struct như sau.

1
2
3
4
5
6
7
typedef struct Product {
  int weight; 
  double price;
} Product;

Product product1 = {.weight = 10, .price = 2.5}; // kiểu tường minh
Product product2 = {10, 2.5}; // kiểu ngắn gọn

Truy cập các thành viên của struct

Sử dụng dấu chấm . để đọc và ghi các thành viên của struct.

1
2
3
4
5
6
7
8
typedef struct Product {
  int weight; 
  double price;
} Product;

Product product1;
product1.weight = 10;
product1.price  = 2.5;

Struct lồng nhau

Struct được coi như một kiểu dữ liệu nên có thể thoải mái khai báo struct lồng nhau.

1
2
3
4
5
6
7
8
9
typedef struct ProductName {
  char* name[10]; 
} ProductName;

typedef struct Product {
  int weight; 
  double price;
  ProductName name;
} Product;

Struct với con trỏ

Để truy cập các thành viên struct của con trỏ thì chúng ta sử dụng toán tử ->

1
2
3
4
5
6
7
8
9
typedef struct Product {
  int weight; 
  double price;
} Product;

Product* pointer = malloc(sizeof(Product));
pointer->weight = 10;
pointer->price =  2.5;
free(pointer);

Căn chỉnh struct (Struct alignment)

Trong các CPU máy tính hiện nay thì việc đọc và ghi dữ liệu hiệu quả khi dữ liệu được căn chỉnh tự nhiên. Ví dụ trên các máy tính 64 bit, dữ liệu sẽ được đọc và ghi 64 bit một lượt. Nên kích cỡ dữ liệu struct cũng nên là bội số của 64 bit (8 bytes).

Với struct trong C, thì nó được căn chỉnh dựa trên kích cỡ của member lớn nhất. Ví dụ struct stu_a dưới đây khi khai báo sẽ có 5 bytes, vì 5 là số lẻ nên nó được trình biên dịch căn chỉnh lại thành 8 bytes.

1
2
3
4
5
typedef struct stu_a {
  char c; // size 1
  int i; // size 4
} stu_a;
sizeof(stu_a); // 8

Trình biên dịch tự động bù vào kiểu dữ liệu trên như sau:

1
2
3
4
5
6
7
typedef struct stu_a {
  char c; // size 1
  // trình biên dịch tự động thêm một dữ liệu có kích thước 3 bytes vào
  char gap_0[3]; // size 3
  int i; // size 4
} stu_a;
sizeof(stu_a); // 8