01/10/2018, 08:39

Sizeof của 1 struct gồm 1 biến char và 1 biến short trên OS 64bit (8-byte alignment) bằng bao nhiêu?

Câu hỏi như tiêu đề.
E có 1 struct như sau:

typedef struct {
     char c;
     short s;
} mystruct;

thì đối với struct này, trên OS 16bit và OS 32bit (4-byte alignment) thì struct đều có size là 4 bytes. Nhưng e thắc mắc là nếu trên OS 32bit (8-byte alignment) và OS 64bit thì kích thước của nó phải là 8 bytes thay vì 4 bytes chứ nhỉ ??
Lý do là vì trên OS 64bit, 1 WORD là 8 bytes => block đầu tiên dùng để chứa biến char c; và biến short s; sẽ có size là 8 bytes mặc dù thực tế chỉ cần có 4 bytes để chứa 2 biến đó.
Suy nghĩ của e nó ntn:

Nhờ các pro giúp đỡ ạ, e cảm ơn trước

rogp10 viết 10:47 ngày 01/10/2018

Không cần thiết vì short chỉ cần 2 byte nên 2-byte alignment là đủ dùng.

Long Dragon viết 10:50 ngày 01/10/2018

E vẫn chưa hiểu lắm ạ @@

nohat viết 10:50 ngày 01/10/2018

Bộ nhớ cấp phát cho 1 biến struct sẽ được tính = một số nguyên lần bộ nhớ của biến có kiểu dữ liệu lớn nhất trong struct. Ví dụ ở trên thì short cần 2 byte, char 1 byte nên bộ nhớ sẽ cần là 4 byte. Và tuỳ thuộc vào trình tự khai báo các thành phần của struct mà bộ nhớ cũng sẽ khác. Trên OS 32 char tốn 1 byte, short 2 byte.

Long Dragon viết 10:50 ngày 01/10/2018

Bộ nhớ cấp phát cho 1 biến struct sẽ được tính = một số nguyên lần bộ nhớ của biến có kiểu dữ liệu lớn nhất trong struct. Ví dụ ở trên thì short cần 2 byte, char 1 byte nên bộ nhớ sẽ cần là 4 byte. Và tuỳ thuộc vào trình tự khai báo các thành phần của struct mà bộ nhớ cũng sẽ khác. Trên OS 32 char tốn 1 byte, short 2 byte.

Ý của e là ntn:
Trên OS 32bit (8-byte alignment) hay OS 64bit thì 1 WORD là 8 bytes, suy ra 1 block cũng 8 bytes. Vậy thì size của struct đó phải 8 bytes chứ ? (mặc dù thực tế chỉ cần 4 bytes để lưu trữ)
Nó ntn:

4 ô cuối (màu nâu) là 4 ô còn dư vì block 8 bytes mà 2 biến char & short chỉ cần 4 bytes => nó phải tính thêm 4 ô dư đó, tổng cộng là 8 bytes chứ nhỉ ?

rogp10 viết 10:45 ngày 01/10/2018

1 WORD là 8 bytes, suy ra 1 block cũng 8 bytes

Suy luận sai Padding block chỉ phụ thuộc hai điều:

  • pragma setting (cả global và local) được ưu tiên xét đến, nhưng không vượt quá kích thước lớn nhất của primitive (VS).
  • Nếu không có pragma thì áp dụng padding theo kích thước lớn nhất của các primitive.

short có 2 byte thì mỗi block 2 byte đúng rồi.

Long Dragon viết 10:53 ngày 01/10/2018

Padding block chỉ phụ thuộc hai điều:

Padding block có phải là kích thước của 1 block ko anh ?

rogp10 viết 10:49 ngày 01/10/2018

Uh. Chắc phải thêm vài ví dụ

  1. Một struct có {int32_t; char; short;}. Biết rằng struct này có kích cỡ là 8 byte Vậy thì short và char nằm ở ô nhớ số mấy trong struct? (đánh số từ 0)
  2. Cũng câu hỏi như trên với {char; int32_t; short;}. Kích cỡ của struct này là bao nhiêu?
  3. Từ đây rút ra điều gì?
Long Dragon viết 10:47 ngày 01/10/2018

Uh. Chắc phải thêm vài ví dụ

E hiểu rồi, thì ra là nếu WORD size > kích thước đường biên thì lấy kích thước đường biên làm giới hạn. Còn nếu WORD size < kích thước đường biên thì lấy WORD size làm giới hạn

  1. Một struct có {int32_t; char; short;}. Biết rằng struct này có kích cỡ là 8 byte Vậy thì short và char nằm ở ô nhớ số mấy trong struct? (đánh số từ 0)

Trên OS 16bit (2-byte alignment): 6 bytes (sizeof(int) = 2 bytes)
Trên OS 32bit (4-byte alignment): 8 bytes
Trên OS 64bit (8-byte alignment): 8 bytes (kích thước đường biên vẫn là 4 bytes mặc dù 1 WORD là 8 bytes)

  1. Cũng câu hỏi như trên với {char; int32_t; short;}. Kích cỡ của struct này là bao nhiêu?

Trên OS 16bit (2-byte alignment): vẫn 6 bytes
Trên OS 32bit (4-byte alignment): 12 bytes (kích thước đường biên là 4)
Trên OS 64bit (8-byte alignment): 12 bytes (kích thước đường biên vẫn là 4 bytes mặc dù WORD size là 8 bytes)

  1. Từ đây rút ra điều gì?

Thay đổi vị trí các biến thành phần của 1 struct thì size của struct đó sẽ bị thay đổi ??

P/S: Em chưa gặp kiểu int32_t bao giờ nên e tạm xem nó giống như kiểu int (4 bytes) luôn nhé anh

Long Dragon viết 10:47 ngày 01/10/2018

Padding block chỉ phụ thuộc hai điều:

  • pragma setting (cả global và local) được ưu tiên xét đến.- Rồi mới tới kích thước lớn nhất của các primitive.

hình như chỗ này cũng phải cân nhắc thêm là nếu giá trị của pragma setting lớn hơn kích thước đường biên (kích thước của biến thành phần lớn nhất) thì compiler sẽ bỏ qua giá trị pragma đó và chọn kích thước đường biên làm giới hạn đúg ko a ?
Tương tự cho WORD size và N-byte alignment ?

rogp10 viết 10:40 ngày 01/10/2018

Không, mình đã nói word size không liên quan. Còn int32_t là chằn chặn 4 byte (32 bit) luôn

hình như chỗ này cũng phải cân nhắc thêm là nếu giá trị của pragma setting lớn hơn kích thước đường biên (kích thước của biến thành phần lớn nhất) thì compiler sẽ bỏ qua giá trị pragma đó và chọn kích thước đường biên làm giới hạn đúg ko a ?

Cái này không đúng vì nếu pragma đấy không override được default alignment thì không ai sử dụng nó cả

(oops pragma lớn hơn thì nó sẽ khác)

Long Dragon viết 10:53 ngày 01/10/2018

Không, mình đã nói word size không liên quan.

Là sao a ?
Nhưng kết quả e đưa ra đúng ko ạ ? E thử test trên ideone thì thấy cũng đúng mà, chỉ có cái OS 16bit ko có chỗ test do int 2 bytes

Cái này không đúng vì nếu pragma đấy không override được default alignment thì không ai sử dụng nó cả

E chưa hiểu lắm ?

rogp10 viết 10:41 ngày 01/10/2018

Bên VS thì có vẻ đúng nhưng hơi mập mờ https://msdn.microsoft.com/en-us/library/2e70t5y1.aspx gcc thì doc ko viết nhiều.

The alignment of a member will be on a boundary that is either a multiple of n or a multiple of the size of the member, whichever is smaller.

Tức là {char; short; } tối đa là pack(2) và 4, 8, 16 không có tác dụng gì.

Long Dragon viết 10:47 ngày 01/10/2018

Bên VS thì có vẻ đúng nhưng hơi mập mờ https://msdn.microsoft.com/en-us/library/2e70t5y1.aspx gcc thì doc ko viết nhiều.

Anh đang reply cho câu hỏi nào thế ạ ?

Tức là {char; short; } tối đa là pack(2) và 4, 8, 16 không có tác dụng gì.

thì như e nói đó, khi N-byte alignment lớn hơn kích thước của biến thành phần lớn nhất trong struct (ở đây là short 2 bytes) thì nó chỉ lấy kích thước của biến đó làm kích thước đường biên chứ ko phải cái N-byte alignment kia nên 4-byte alignment hay 8-byte alignment (#pragma pack (4/8)) ko có tác dụng ấy

rogp10 viết 10:54 ngày 01/10/2018

Anh đang reply cho câu hỏi nào thế ạ ?

Post #10 đó bạn.

Vậy có khi phải sửa lại nào giờ chưa thấy ai pack 2/4/8 cả, toàn pack 1 thôi. Vả lại chỗ đó rất mập mờ: số đã chia hết cho 8 thì cũng phải chia hết cho 4. Phải chạy thử mới dám chắc được.

Long Dragon viết 10:43 ngày 01/10/2018

Vả lại chỗ đó rất mập mờ

Chỗ nào ạ ? ^^

p/s: công nhận cái này nhức đầu thật, hèn j mấy thằng bạn bảo qua con trỏ với struct là nát óc ._.

rogp10 viết 10:44 ngày 01/10/2018

Chỗ nào ạ ? ^^

Link bên MSDN ấy bạn.[quote=“phamhoanglong, post:16, topic:42950”]
p/s: công nhận cái này nhức đầu thật, hèn j mấy thằng bạn bảo qua con trỏ với struct là nát óc ._.
[/quote]

Cái pack này hay gặp ở 3 bối cảnh:

  • Viết code driver, firmware (pack(1)) hay code embedded
  • Viết code mạng (pack(1))
  • Serialization (khi đổi toolchain thì sẽ có khả năng sinh những lỗi trời ơi)
huyentrang viết 10:45 ngày 01/10/2018
  1. char nằm ô 4 và short nằm ô 5 ạ?
Bài liên quan
0