STDIO
Tìm kiếm gần đây
    Nội dung
    0
    0
    Chia sẻ
    Nội dung
    0
    0
    Chia sẻ

    Struct Alignment trong C++

    Tìm hiểu về Struct Alignment trong C/C++.
    08/10/2015 10/09/2020 5 phút đọc
    Struct Alignment trong C++

    C/C++ cung cấp cho chúng ta một số kiểu dữ liệu cơ bản như char, int, float, double, long... C/C++ cũng cho phép chúng ta tạo ra những kiểu dữ liệu mới tổng hợp nhiều kiểu dữ liệu bằng cách dùng struct, class. Việc cấp phát và tổ chức bộ nhớ đối với dữ liệu cơ bản là khá đơn giản, còn đối với struct, class thì cấp phát, tổ chức bộ nhớ như thế nào.

    Thông tin chi tiết về các kiểu dữ liệu này được thể hiện ở bảng dưới:

    KIỂU DỮ LIỆU KÍCH THƯỚC MIỀN GIÁ TRỊ
    char 1 byte -127 to 127 or 0 to 255
    unsigned char 1 byte 0 to 255
    signed char 1 byte -127 to 127
    int 4 bytes   -2147483648 to 2147483647
    unsigned int 4 bytes  0 to 4294967295
    signed int 4 bytes -2147483648 to 2147483647
    short int 2 bytes -32768 to 32767
    unsigned short int   2 bytes 0 to 65,535
    signed short int   2 bytes -32768 to 32767
    long int  4 bytes -2,147,483,647 to 2,147,483,647
    signed long int 4 bytes -2,147,483,647 to 2,147,483,647
    unsigned long int 4 bytes 0 to 4,294,967,295
    float       4 bytes +/- 3.4e +/- 38 (~7 digits)
    double    8 bytes +/- 1.7e +/- 308 (~15 digits)
    long double 8 bytes +/- 1.7e +/- 308 (~15 digits)

    Trước khi đi vào chủ đề của bài viết bạn cần nắm rõ những biến này được tổ chức như thế nào trên bộ nhớ. Giả sử tôi có những câu lệnh dưới đây:

    int id = 13520546;        // 4 bytes
    double salary = 500.000;  // 8 bytes

    Và tổ chức bộ nhớ sẽ là:

    Vùng nhớ của id và salary có thể là không liên tục trên bộ nhớ.

    Kết quả khi chạy chương trình dưới đây và in ra địa chỉ của hai biến id và salary:

    int id = 13520546;
    double salary = 500.000;
    printf("id address: %d\nsalary address: %d\n", &id, &salary);

    Tổ chức bộ nhớ trong struct, class

    Tôi tạo một struct Point thể hiện tọa độ của điểm trong không gian hai chiều:

    struct Point
    {
    	int x;
    	int y;
    };
    

    Lấy kích thước của struct bằng cách sử dụng toán tử sizeof được cung cấp trong C++, kích thước của nó là 8 bytes đúng bằng các kích thước các trường dữ liệu thành viên cộng lại.

    Tạo tiếp một struct Student thể hiện thông tin của một sinh viên gồm id, age, gpa là điểm trung bình học kì:

    struct Student
    {
    	char id;
    	int age;
    	double gpa;
    };

    Lấy kích thước của của struct Student:

    int size = sizeof(Student);

    Kích thước mong đợi là 13 bytes bằng kích thước của id (1 bytes) cộng với age (4 bytes) và gpa (8 bytes). Nhưng thực tế kích thước có thể là 16 bytes.

    Đầu tiên trình biên dịch sẽ lấy kích thước của trường dữ liệu thành viên có kích thước lớn nhất (theo đơn vị byte) mà kích thước đó là lũy thừa của 2.

    Trong trường hợp này là 8 bytes theo kích thước của gpa.

    Sau đó cấp phát 1 block gồm đúng bằng kích thước này là 8 bytes, id với kích thức 1 bytes sẽ ở vị trí như hình dưới:

    Ta vẫn còn 7 chỗ trống, ở đây tùy theo trình biên dịch mà nó sẽ padding bao nhiêu bytes rồi "đẩy" age kiểu int có kích thước 4 bytes vào:

    Đã hết chỗ trống, tiếp tục cấp thêm block 8 bytes nữa và "đẩy" gpa kiểu double có kích thước 8 bytes vào:

    Vậy kích thước của struct này là 16 bytes.

    Vùng nhớ cấp phát cho struct luôn luôn là liên tục trong bộ nhớ như ở trên ta thấy là địa chỉ của id, age, gpa lần lượt là 0x04, 0x08, 0xC.

    Khảo sát thêm một struct nữa có tên là Demo

    struct Demo
    {
        int a, b;
        double c, d;
    };

    Kích thước struct này là: 24 bytes;

    Sắp xếp lại các trường dữ liệu như sau:

    struct Demo
    {
        int a;
        double c, d;
        int b;
    };

    Kiểm tra thấy kích thức của struct này là 32 bytes

    Như vậy struct có cùng các trường dữ liệu như nhau, nhưng nếu thay đổi vị trí của chúng trong struct thì có thể thay đổi kích thước của struct đó. Dựa vào cách sắp xếp bộ nhớ trong struct mà tôi đã trình bày ở trên giúp các bạn có thể tránh được việc mất mát vùng nhớ.

    Lưu ý: Cách tổ chức bộ nhớ trong class cũng tượng tự như struct.

    Struct, class không có dữ liệu thành viên

    Chúng ta đã khảo sát struct có các trường dữ liệu, nếu struct đó không có dữ liệu thành viên thì sao, việc lưu trữ như thế nào? Một ví dụ điển hình là class xử lý toán học Math trong C#. 

    struct Person
    {
        
    };

    1 struct Person không có thành viên và lấy kích thước của nó như bên dưới:

    int size = sizeof(Person);

    Kích thước sẽ là 1 byte. Đối với những struct hay class như thế này thì trình biên dịch sẽ cấp phát 1 byte để có thể lưu trữ nó dưới bộ nhớ.

    Tạo 1 biến có tên là person và lấy địa chỉ của nó trong bộ nhớ: 

    Person person;
    printf("Address of person %d\n", &person);

    Kết quả in lên màn hình

    Địa chỉ của struct, class

    Cũng giống như mảng, địa chỉ của mảng chính là địa chỉ của phần tử đầu tiên, đối với class, struct cũng vậy. Địa chỉ của nó chính là địa chỉ của thành viên đầu tiên trong struct, class đó.

    struct Student
    {
        char id;
        int age;
        double gpa;
    };
    
    int main()
    {
    	Student student;
    	printf("Address of student: %d\n", &student);
    	printf("Address of student.id: %d\n", &student.id);
    	printf("Address of student.age: %d\n", &student.age);
    	printf("Address of student.gpa: %d\n", &student.gpa);
        return 0;
    }

    Và kết quả cho thấy rằng địa chỉ của student cũng chính là địa chỉ của  id trong struct đó:

    0 Bình luận
    Modern C++

    Modern C++

    STDIO Training - Đào Tạo Lập Trình C++.

    Khi bạn nhấn vào sản phẩm do chúng tôi đề xuất và mua hàng, chúng tôi sẽ nhận được hoa hồng. Điều này hỗ trợ chúng tôi có thêm kinh phí tạo nhiều nội dung hữu ích. Tìm hiểu thêm.
    STDIO

    Trang chính

    Công ty TNHH STDIO

    • 30, Trịnh Đình Thảo, Hòa Thạnh, Tân Phú, Hồ Chí Minh
      +84 28.36205514 - +84 942.111912
      developer@stdio.vn
    • 383/1 Quang Trung, Phường 10, Quận Gò Vấp, Hồ Chí Minh
      Số giấy phép ĐKKD: 0311563559 do sở Kế hoạch và Đầu Tư TPHCM cấp ngày 23/02/2012
    ©STDIO, 2013 - 2021