Tôi muốn lấy một phần dữ liệu bên trong một số cấu trúc C để sắp xếp từng phần/deserialize chúng, ghi byte từ bộ nhớ vào đĩa và ngược lại.sizeof() một phần của cấu trúc C - loại
Các cấu trúc không được biết trước, chúng được tạo động bằng trình tạo mã C của riêng tôi (cũng như mã sẽ tuần tự hóa nó). Các trường tuần tự sẽ được đặt ở đầu cấu trúc.
Hãy nói rằng một có một cấu trúc với 4 lĩnh vực, và hai đầu tiên sẽ được đăng:
typedef struct {
int8_t x1;
int32_t x2; /* 1 + 4 = 5 bytes (if packed) */
int8_t y1;
int32_t y2; /* 1 + 4 +1 + 4 = 10 bytes (if packed) */
} st;
tôi dự định lấy con trỏ vào biến struct và viết/đọc n
byte bao gồm những hai trường đầu tiên (x1, x2
). Tôi không nghĩ rằng tôi cần phải lo lắng về sự liên kết/đóng gói bởi vì tôi không có ý định serialization để tồn tại compilations khác nhau (chỉ có một thực thi duy nhất dự kiến sẽ đọc/ghi dữ liệu). Và, khi tôi đang nhắm mục tiêu một phạm vi rộng của các kiến trúc trình biên dịch, tôi không muốn đặt các giả định về thủ thuật đóng gói liên kết hoặc trình biên dịch cụ thể.
Sau đó, tôi cần tính số byte. Và tôi không thể chỉ làm sizeof(st.x1)+sizeof(st.x2)
vì việc làm đệm lót. Vì vậy, tôi đang lập kế hoạch để trừ con trỏ, từ khi bắt đầu cấu trúc đến trường "không liên tục" đầu tiên:
st myst;
int partsize = (char*)&myst.y1 - (char*)(&myst);
printf("partial size=%d (total size=%d)\n",partsize,sizeof(myst));
Điều này dường như hoạt động. Và nó có thể được đặt trong một macro.
(Đối với bản ghi: Tôi đã thử viết một macro khác không trả lại một thể hiện của cấu trúc, chẳng hạn như this, nhưng dường như không thể ở đây - nhưng điều này không quan trọng đối với tôi nhiều).
Câu hỏi của tôi: Điều này có chính xác và an toàn không? Bạn có thể thấy bất kỳ cạm bẫy tiềm năng nào, hoặc một số cách tiếp cận tốt hơn?
Trong số những thứ khác: Các tiêu chuẩn C (và trình biên dịch thực tế) có giả định rằng các trường cấu trúc nằm trong bộ nhớ theo cùng thứ tự như chúng được định nghĩa trong nguồn không? Điều này có lẽ là một câu hỏi ngu ngốc, nhưng tôi muốn chắc chắn ...
UPDATE: Một số kết luận từ các câu trả lời và những phát hiện của riêng tôi:
Có vẻ là không có vấn đề với cách tiếp cận của tôi . Đặc biệt, C quy định rằng các trường struct sẽ không bao giờ thay đổi thứ tự.
Một cũng có thể (như được đề xuất bằng số aswer) từ trường liên tục cuối cùng và thêm kích thước của nó:
(char*)&myst.x2 + sizeof(&myst.x2) - (char*)(&myst)
. Điều đó sẽ tương đương, ngoại trừ việc nó sẽ bao gồm không phải byte đệm (nếu có) cho trường cuối cùng. Một lợi thế rất nhỏ - và một nhược điểm rất nhỏ, trong việc ít đơn giản hơn.Nhưng câu trả lời được chấp nhận, với
offsetof
, dường như thích hợp hơn đề xuất của tôi. Đó là thời gian biên dịch rõ ràng và thuần khiết, nó không đòi hỏi một thể hiện của cấu trúc. Nó tiếp tục có vẻ là tiêu chuẩn, có sẵn trong bất kỳ trình biên dịch. Nếu người ta không cần một cấu trúc biên dịch thời gian, và có một thể hiện của cấu trúc có sẵn (như là kịch bản của tôi) cả hai giải pháp đều tương đương nhau.
Câu hỏi liên quan: http://stackoverflow.com/questions/2748995/c-struct-memory-layout – payne
Tôi đã xóa thẻ C++, vì không có C++ ở bất kỳ đâu gần câu hỏi này. – Puppy