Từ 1 tới 9 trên tổng số 9 kết quả

Đề tài: Tổ chức bộ nhớ trong Class và trong Struct (Alignment and Padding)

  1. #1
    Ngày gia nhập
    04 2008
    Nơi ở
    Bốn bề là nhà
    Bài viết
    703

    Mặc định Tổ chức bộ nhớ trong Class và trong Struct (Alignment and Padding)

    Đặt vấn đề: Gần đây có 1 số thành viên thắc mắc về vấn đề này, và mình có tìm hiểu qua trong diễn đàn chưa có bài viết nào thật sự chi tiết về vấn đề này, vì vậy mạo muội được viết 1 tut để giải thích sơ lược
    Tài liệu tham khảo từ Top 20 tips C++, MSDN, trình bày theo cách hiểu của mình, do hiểu biết còn hạn hẹp, nên chắc chắn có sai sót. Mong anh em thông cảm.

    Tổng quan: Các kiểu dữ liệu được xây dựng sẵn (built-in) đều có 1 kích thước cố định (được tính bằng số byte của nó), tùy thuộc vào từng compiler, nhưng thông thường kích cỡ của nó như sau:
    C++ Code:
    1. #include <iostream.h>
    2. #include <math.h>
    3. int main()
    4. {
    5.     cout<<"Bool    :"<<sizeof(bool)<<endl;
    6.     cout<<"Char    :"<<sizeof(char)<<endl;
    7.     cout<<"Int      :"<<sizeof(int)<<endl;
    8.     cout<<"Float   :"<<sizeof(float)<<endl;
    9.     cout<<"Double :"<<sizeof(double)<<endl;  
    10.     system("PAUSE");
    11.     return 0;
    12. }
    Kết quả:
    Click vào hình ảnh để lấy hình ảnh lớn

Tên:		1.jpg
Lần xem:	296
Size:		29.0 KB
ID:		5749

    Bây giờ hẳn nhiều bạn sẽ quan tâm vậy kiểu dữ liệu do người dùng tự định nghĩa (typedef) như Class, Struct thì size của nó bằng bao nhiêu?
    Suy nghĩ tự nhiên của mỗi người là: nó bằng tổng của các thành phần. Ta đi xem vài vd sau:
    C Code:
    1. #include <iostream.h>
    2.  
    3. class A
    4. {
    5.       int a1;
    6.       int b1;
    7.       char c1,c2,c3,c4;
    8. };
    9.  
    10. class B
    11. {
    12.       int a,b;
    13.       double b1,b2;
    14. };
    15. int main()
    16. {
    17.     cout<<"Class A   :"<<sizeof(A)<<endl;    
    18.     cout<<"Class B   :"<<sizeof(B)<<endl;  
    19.     system("PAUSE");
    20.     return 0;
    21. }
    Kết quả:

    Click vào hình ảnh để lấy hình ảnh lớn

Tên:		2.jpg
Lần xem:	293
Size:		28.4 KB
ID:		5750
    Có vẻ đúng vì:
    C++ Code:
    1. SizeOf(A)=4+4+1+1+1+1=12;
    2. SizeOf(B)=4+4+8+8=24;
    Nhưng giờ nếu ta thay đổi thế này:
    C++ Code:
    1. #include <iostream.h>
    2.  
    3. class A
    4. {
    5.       int a1;
    6.       int b1;
    7.       char c1,c2,c3,c4;
    8. };
    9.  
    10. class B
    11. {
    12.       int a;
    13.       double b1,b2;
    14.       int b;
    15. };
    16. int main()
    17. {
    18.     cout<<"Class A   :"<<sizeof(A)<<endl;    
    19.     cout<<"Class B   :"<<sizeof(B)<<endl;  
    20.     system("PAUSE");
    21.     return 0;
    22. }
    Thì ta lại được kết quả như sau:
    Click vào hình ảnh để lấy hình ảnh lớn

Tên:		3.jpg
Lần xem:	303
Size:		28.1 KB
ID:		5751
    Lý do là như sau: Trong các Class (hoặc Struct) nó sẽ tìm xem kiểu của dữ liệu lớn nhất trong các thành phần của nó là gì? Rồi chọn nó để làm "lề" (Alignment), sau đó nó sẽ làm như sau:
    Duyệt các biến thành viên từ đầu đến hết, với mỗi biến ta sẽ xem có "nhét" (Padding) vào phần thừa trước đó được không? Nếu được thì "nhét", ngược lại sử dụng thêm 1 đoạn mới, lúc này Size của Class đó sẽ tăng lên 1 kích thước là số byte của Alignment.
    Haizzzzzzzzzzz, diễn tả bằng lời nói thật khó tại hạ xin được dùng hình ảnh cho dễ hiểu:
    Ta xét với Class B
    + Ban đầu ta khai báo:
    C++ Code:
    1. class B
    2. {
    3.       int a,b;
    4.       double b1,b2;
    5. };
    kiểu dữ liệu lớn nhất trong Class là 8 byte, nên độ rộng của lề là 8 byte.
    Click vào hình ảnh để lấy hình ảnh lớn

Tên:		4.jpg
Lần xem:	5
Size:		23.9 KB
ID:		5752
    Đầu tiên xét với thằng
    C++ Code:
    1. a = 4 byte
    vẫn còn trống nên nhét nó vô, được như sau
    Click vào hình ảnh để lấy hình ảnh lớn

Tên:		5.jpg
Lần xem:	6
Size:		24.6 KB
ID:		5753
    Giờ đến thằng
    C++ Code:
    1. b = 4 byte
    Vẫn còn đủ chỗ cho nó => "nhét" vô, được như sau:
    Click vào hình ảnh để lấy hình ảnh lớn

Tên:		6.jpg
Lần xem:	4
Size:		29.5 KB
ID:		5754
    Giờ đến thằng
    C++ Code:
    1. b1 = 8 byte
    . Do đã hết chỗ "trống" nên ta phải thêm 1 đoạn (segment) mới, rồi nhét nó vô, được như sau:
    Click vào hình ảnh để lấy hình ảnh lớn

Tên:		7.jpg
Lần xem:	4
Size:		38.2 KB
ID:		5755
    Tương tự đối với
    C++ Code:
    1. b2 = 8 byte
    . Ta lại phải thêm 1 segment nữa cho nó. Kết quả được như sau:
    Click vào hình ảnh để lấy hình ảnh lớn

Tên:		8.jpg
Lần xem:	4
Size:		59.4 KB
ID:		5756
    Như vậy
    C++ Code:
    1. SizeOf (B) =3 segment * 8 (byte/segment) = 24 byte
    Bây giờ ta đi xem xét trường hợp khai báo thứ 2:
    C++ Code:
    1. class B
    2. {
    3.       int a;
    4.       double b1,b2;
    5.       int b;
    6. };
    Quá trình ban đầu vẫn diễn ra hệt như trên, sau khi đã nhét xong thằng a. Ta được hình ảnh sơ bộ như thế này:Click vào hình ảnh để lấy hình ảnh lớn

Tên:		5.jpg
Lần xem:	6
Size:		24.6 KB
ID:		5753.
    Tiếp đến với
    C++ Code:
    1. b1 = 8 byte
    , do nó có độ rộng là 8 byte trong khi còn thừa có 4 byte => Phải thêm 1 segment nữa, và ta được hình ảnh như sau:
    Click vào hình ảnh để lấy hình ảnh lớn

Tên:		9.jpg
Lần xem:	4
Size:		37.2 KB
ID:		5757
    Lần lượt như vậy cuối cùng ta được:
    Click vào hình ảnh để lấy hình ảnh lớn

Tên:		10.jpg
Lần xem:	5
Size:		71.4 KB
ID:		5758
    Điều đó giải thích tại sao trong lần khai báo thứ 2 ta lại có kết quả 32 byte
    Kết luận: Hi vọng với những ví dụ trên các anh em có thể hiểu được phần nào về cách tổ chức của Class và Struct, để từ đó có những cách t/c hợp lý hơn, tránh lãng phí bộ nhớ.
    P/S: T/p đầu tay của e, các bác nên nhìn với thái độ "khoan dung" 1 tí
    Đã được chỉnh sửa lần cuối bởi G.Perelman : 02-04-2011 lúc 11:33 PM.

  2. #2
    Ngày gia nhập
    03 2011
    Nơi ở
    Bình Dương, Hồ Chí Minh
    Bài viết
    392

    haiz...có những cái không ngờ đến....Cảm ơn bạn nhiều!

  3. #3
    Ngày gia nhập
    04 2008
    Nơi ở
    Bốn bề là nhà
    Bài viết
    703

    Đúng là những điều này chính t cũng không ngờ đến, có lần vì tò mò t xem size của các class và struct nó như thế nào, thấy nó không bình thường, nên mới tìm hiểu được như vậy.

  4. #4
    Ngày gia nhập
    10 2011
    Bài viết
    1

    thanks bạn nhiều nha

  5. #5
    Ngày gia nhập
    09 2012
    Bài viết
    2

    Thanks bạn nhiều. ^^

  6. #6
    Ngày gia nhập
    12 2010
    Bài viết
    42

    Mặc định Tổ chức bộ nhớ trong Class và trong Struct (Alignment and Padding)

    Quá hay. Cảm ơn bạn nhiều.

  7. #7
    Ngày gia nhập
    06 2011
    Bài viết
    39

    cách mình thường dùng để giải quyết vấn đề này là tất cả dữ liệu trong class đều lưu trữ dưới dạng mảng kiểu char, mỗi lần muốn truy cập đều phải gọi đến hàm trả về tham chiếu
    VD:
    C++ Code:
    1. class A
    2. {    
    3.     int a;
    4.     double b;
    5. };

    ->

    C++ Code:
    1. class A
    2. {
    3.     public:
    4.     A(){}
    5.  
    6.     int &ra()
    7.     {
    8.         int &res=*((int*)(&data[0]));
    9.         return res;
    10.     }
    11.     double &rb()
    12.     {
    13.         double &res=*((double*)(&data[4]));
    14.         return res;
    15.     }
    16.     private:
    17.     char data[12];
    18. };

    có ai có cách tốt hơn không ?
    Press any key to continue
    fuck china

  8. #8
    Ngày gia nhập
    01 2013
    Bài viết
    1,479

    ^ Bạn cần byte alignment để làm gì?

    #pragma pack(1)

  9. #9
    Ngày gia nhập
    05 2011
    Bài viết
    2

    Bài viết rất hay, các bạn có thể tham khảo thêm ở đây
    https://en.wikipedia.org/wiki/Data_structure_alignment

Các đề tài tương tự

  1. Khai báo một struct trong 1 class như thế nào?
    Gửi bởi hoanglamth1 trong diễn đàn Thắc mắc CTDL & Giải thuật
    Trả lời: 1
    Bài viết cuối: 22-11-2011, 10:42 AM
  2. So sánh class và struct trong C++?
    Gửi bởi Meo_beo_123 trong diễn đàn Nhập môn lập trình C/C++
    Trả lời: 1
    Bài viết cuối: 13-03-2011, 01:05 PM
  3. những thành phần bắt buộc phải có trong hàm delete của struct/class ?
    Gửi bởi kukopuka trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 21
    Bài viết cuối: 20-02-2011, 09:36 PM
  4. Data Alignment Trong C++
    Gửi bởi C&C++ trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 1
    Bài viết cuối: 14-07-2010, 04:04 PM
  5. Lập trình C++ | Tùy chọn biên dịch struct alignment
    Gửi bởi Kevin Hoang trong diễn đàn Thủ thuật, Tutorials và Mã nguồn C/C++/C++0x
    Trả lời: 0
    Bài viết cuối: 30-07-2006, 01:59 PM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn