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 :blush:

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

2 Likes

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

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.

1 Like

Ý 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ỉ ? :thinking:

Suy luận sai :slight_smile: 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.

2 Likes

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

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

  1. Một struct có {int32_t; char; short;}. Biết rằng struct này có kích cỡ là 8 byte :slight_smile: 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ì?
1 Like

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 :slight_smile:

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)

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)

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 :joy:

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 ? :slight_smile:

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 :slight_smile:

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ả :slight_smile:

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

1 Like

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 :smile:

E chưa hiểu lắm ?

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

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

1 Like

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

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 :slight_smile:

Post #10 đó bạn.

Vậy có khi phải sửa lại :smiley: 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.

2 Likes

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 ._.

Link bên MSDN ấy bạn.

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)
1 Like
  1. char nằm ô 4 và short nằm ô 5 ạ?
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?