#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?
#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?
8
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ái char 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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct __attribute__((__packed__))
{
int y;
char x;
}mystruct;
int main (){
printf("%d", sizeof(mystruct));
}
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:
#pragma pack(push) // begin of struct
#pragma pack(1)
...
#pragma pop // end of struct
struct MyPackedData
{
char Data1;
long Data2 __attribute__((packed));
char Data3;
};
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
typedef struct __attribute__((__packed__))
{
int y;
char x;
}mystruct;
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
typedef struct __attribute__((__packed__))
{
char c1;
int i;
char c2;
} mstruct;
int main(int argc, char** argv)
{
mstruct t;
printf("size %ld\n", sizeof(t));
printf("%x %x %x\n", &t.c1, &t.i, &t.c2);
return 0;
}
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
size 6
6cd847f0 6cd847f1 6cd847f5
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
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
typedef struct
{
short s1;
short s2;
short s3;
} mstruct;
int main(int argc, char** argv)
{
mstruct st1, st2;
printf ("Size: %ld\n", sizeof(mstruct));
printf ("st1: %x st2: %x\n", &st1, &st2);
return 0;
}
Result:
Size: 6
st1: ec8a2e50 st2: ec8a2e60
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.
#include <stdio.h>
typedef struct
{
short s1;
short s2;
short s3;
} mstruct;
int main(int argc, char** argv)
{
mstruct st1, st2;
printf ("Size: %ld\n", sizeof(mstruct));
printf ("st1: %x st2: %x\n", &st1, &st2);
return 0;
}
Result:
Size: 6
st1: 28ff1a st2: 28ff14
Em thử giải thích cái này thử xem, cái này a bị khó hiểu rồi à nha