30/09/2018, 16:04
Cùng đặt vấn đề nào (Bản số 9)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char x;
int y;
}mystruct;
int main (){
printf("%d", sizeof(mystruct));
}
Cái gì sẽ được in ra, giải thích?
Bài liên quan
In ra kích thước của
mystruct
. Nếu tính bằng tay mình sẽ thấy nó có 5 bytes à. Nhưng thực tế khi mình in ra trong bài này nó phải ra tới 8 bytes. Cái này gọi làstruct padding
, nó làm tròn cáichar x
từ 1 byte lên tới 4 bytes. Cái này hình như để tăng tốc độ truy vấn, để anh tìm hiểu lại và xác nhận cái này.Tuy nhiên cũng có một cách để nó in ra đúng 5 bytes đó là mình bắt buộc nó phải đóng gói đúng như vậy
Thế mà giờ em mới biết có cái kiểu đóng gói này đấy, dùng oke với C và C++ luôn phải không anh?
Mà không hình như có lỗi rồi anh à, sao em chạy ko được
Anh không nhớ rõ nó là C hay C++, em thử với C++ xem. Anh đang chạy với C++.
Có vài cách để mình pack struct lại ko cho padding:
cái
#pragma pack(1)
là để thông báo cho compiler biết là mức đóng gói là 1 byte đúng không Vậy mặc định chắc phải là 2 hoặc 4 bytes rồi.long Data2 __attribute__((packed));
Cái này là sao, sao mình lại pack cái thằng bự nhất?Đúng rồi a Đạt, pack(1) là để thông báo mình đóng gói mức 1 bytes.
Mình pack thằng bư nhất, vì nó là thằng gây ra padding cho mấy thằng còn lại :D. Nó sẽ có 3 bytes nằm cùng 1 WORD với thằng char Data1 và 1 byte nằm cùng 1 WORD với thằng Data2
À, cứ nắm đầu thằng bự nhất, rồi kêu nó phải tự đi tìm mấy thằng khác để chia sẻ vùng nhớ à. Thế anh thấy viết như vầy dễ xài hơn. Cái này copy trên mạng hehe
hay quá, có thêm skills mới rồi
Chạy thử đoạn code sau mình sẽ thấy rõ hơn
Result: ta thấy giữa biến c1 và biến i chỉ cách nhau 1 offset -> ko có padding giữa 2 biến này, tức là biến i bị chia ra nằm trên 2 WORD khác nhau
Hay, cái này mới thấy lần đầu à nha. Địa chỉ bị chia ra. Làm như thế này sẽ tiết kiệm được bộ nhớ. Mà hình như nó sẽ truy xuất chậm hơn đúng không @ddhuy137
nó sẽ tốn hơn 2 cycle của CPU để đọc thằng này ra. Vì 1 lần CPU chỉ đọc 1 WORD thôi, nhưng trong TH này phải đọc 2 WORD rồi còn phải shift left, shift right, and, or gì đó nữa để ra đúng value
Khi gán lại cũng vậy
Cao siêu quá @ddhuy137
Như bài toán sau đây, mình sẽ không thấy có padding, nhưng nên cẩn thận nó vẫn được aligment trên memory đó.
Size luôn là 6 bytes, thông thường ta sẽ nghĩ là 2 biến st1 & st2 cách nhau 6 offset (đúng bằng sizeof của struct này) trên memory
Nhưng thưc tế địa chỉ của 2 biến st1 & st2 sẽ cách nhau:
6bytes: nếu là system 16bit / 32 bit
16bytes: nếu là system 64bit
Result:
Vậy có nghĩa là dữ liệu bị đứt quãng, anh hiểu vậy có đúng không Huy?
Dữ liệu vẫn nằm liên mạch anh :). Nhưng nó sẽ padding & alignment trên memory vì CPU của mình 1 lần sẽ đọc 1 WORD lên, nên nếu để 2 biến này hoàn toàn trên 2 WORD khác nhau thì sẽ đọc & xử lý nhanh hơn.
Nhưng theo anh biết 1 WORD có 4 bytes chứ mấy, làm sao đọc được 1 phát 6 bytes giờ?
Đúng là anh thấy 2 thằng này cách nhau tới 16 offset (0x60-0x50). Nhưng mà ở đây mình nói là DWORD mới đúng. Vì DWORD = 8 Bytes.
Sorry anh, e compile trên system 64bit nên WORD của nó bằng 8bytes :D.
Anh Dat & @Dung_Kon thử compile trên 32bit xem.
Result:
Em thử giải thích cái này thử xem, cái này a bị khó hiểu rồi à nha
Đã tìm được lý do
Chính xác là do compiler. Như vậy việc runtime alignment là tùy thuộc vào compiler và các option của nó.
Compile with cl compiler (x86):