2011-11-30 23 views
5
typedef struct node{ 
    char one; 
    char two; 
    struct node *next; 
} nodea; 

Tôi đang nghĩ về khía cạnh trình biên dịch, có cách nào tôi có thể tạo sizeof (nodea) nhỏ hơn 16 không?Kích thước nhỏ nhất mà tôi có thể tạo ra cấu trúc này trên máy 64bit là gì?

+0

Tôi nghĩ rằng với đóng gói chặt chẽ, bạn sẽ kết thúc với 8 byte cho con trỏ và 2 byte cho các nhân vật ... nhưng không chắc chắn 100%. Hãy xem #pragmas cho trình biên dịch của bạn có ảnh hưởng đến việc đóng gói cấu trúc, chọn một gói cung cấp đóng gói chặt chẽ nhất và thử sizeof(). –

+0

Trên nền tảng nào, 32bit hoặc 64bit, trình biên dịch (phiên bản) nào? –

Trả lời

5

Bạn có thể sử dụng các chỉ thị biên dịch #pragma packhttp://msdn.microsoft.com/en-us/library/2e70t5y1%28v=vs.80%29.aspx

#pragma pack(push) 
#pragma pack(1) 
typedef struct node { 
    char one; 
    char two; 
    struct node* next; 
} nodea; 
#pragma pack(pop) 
+0

Quên đề cập đến, tôi đang sử dụng gcc – jck

+0

Nên gần như giống hệt nhau trên gcc. Xem http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html –

+3

Hãy nhớ rằng việc sử dụng cấu trúc này cho danh sách được liên kết sẽ làm giảm hiệu suất tổng thể của danh sách, vì địa chỉ của nút tiếp theo không được căn chỉnh . Cố gắng đặt 'struct node * next' làm mục đầu tiên của cấu trúc.Vì vậy, địa chỉ sẽ luôn luôn được căn chỉnh và nó có thể được lấy trong một hướng dẫn/chu kỳ cho thuê có thể. – DipSwitch

4

Bạn có thể làm cho nó 10 byte nếu bạn gói nó, giả sử phần cứng cơ bản không có bất kỳ yêu cầu liên kết cụ thể. Hãy lưu ý rằng khi bạn bắt đầu đóng gói, bạn sẽ để lại tính di động sau.

Cách ảnh hưởng đến đóng gói tùy thuộc vào trình biên dịch của bạn nhưng hầu hết các trình biên dịch, bao gồm gcc, hỗ trợ #pragma pack chỉ thị loại.

5

Trừ khi đó là một cái gì đó độc đáo, nó có thể được đóng gói thành 1 + 1 + 8 = 10 byte. Nếu con trỏ phải được căn chỉnh, thì 16 byte. Nếu bạn đặt con trỏ đầu tiên và ký tự tiếp theo, sau đó 10 byte, nhưng các yêu cầu căn chỉnh có thể vẫn làm cho nó 16 khi bạn tạo một mảng của các cấu trúc này.

1

Đây là trình biên dịch phụ thuộc. Thông thường bạn có thể kiểm soát sự liên kết của các trường/biến cấu trúc. Ví dụ: với gcc, bạn có thể sử dụng

typedef struct __attribute__ ((packed)) node { 
    char one; 
    char two; 
    struct node *next; 
} nodea; 

để nhận 10 cho sizeof(nodea) trên nền tảng 64 bit.

+0

Luôn đóng gói toàn bộ cấu trúc chứ không chỉ là một biến trong cấu trúc. 'typedef struct __attribute__ ((đóng gói)) nút {...' – DipSwitch

+0

Nó chỉ là một ví dụ từ [tài liệu GNU] (http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html). Và "luôn luôn" mọi thứ phụ thuộc vào nhiệm vụ, phải không? –

+0

Thông thường bạn sẽ đóng gói toàn bộ cấu trúc vì điều này dễ đọc hơn. Hơn nữa là khó hơn để dự đoán kích thước struct (ai đó sẽ cần phải suy nghĩ khó khăn hơn) để ngăn chặn kích thước struct cuối. Ngoài ra nếu bạn thêm một char sau khi mục nút này sẽ vẫn còn sử dụng 8 byte cho char đơn, vì đây là kích thước từ của bộ vi xử lý. Mà cũng có thể dẫn đến một số behaviorism undefined nếu bạn ví dụ muốn đọc một tập tin dữ liệu được lưu trữ đã được tạo ra trên một kiến ​​trúc 64bit và được đọc trên một kiến ​​trúc 32bit. – DipSwitch

0

Sử dụng đóng gói trên cấu trúc cũng có nghĩa là trình biên dịch không thể sắp xếp lại cấu trúc dữ liệu, trên một số nền tảng đóng gói có thể giảm hiệu suất rất lớn. Một số bộ vi xử lý không thể nhận được các từ chưa được ký kết vì vậy nếu mã sẽ được biên dịch trên nền tảng đó thì trình biên dịch sẽ buộc phải lấy từ trên mỗi byte và dịch chuyển mọi thứ ở đúng nơi, đây chắc chắn là thứ bạn không muốn. Đặc biệt không có trong danh sách liên kết vì điều này sẽ làm cho danh sách của bạn thực sự thực sự rất chậm truy cập ... Và ngay cả khi cpu hỗ trợ unaligned nhận được CPU sẽ cần phải thực hiện thêm chu kỳ để đọc từ 2 địa chỉ trong bộ nhớ và concat chúng một lần nữa.

Đây là lý do tại sao bạn phải xem cách bạn có thể trợ giúp trình biên dịch. Bạn sẽ muốn bạn cấu trúc được từ liên kết để địa chỉ của nút tiếp theo luôn luôn có thể được đọc với một hướng dẫn đọc duy nhất. Điều này có nghĩa là đối với kiến ​​trúc 64bit bạn muốn đặt con trỏ của nút tiếp theo lên trên, do đó, điều này luôn được căn chỉnh, tiếp theo bạn sẽ muốn đảm bảo rằng nếu bạn sử dụng cấu trúc trong mảng, địa chỉ struct node * sẽ luôn là liên kết, vì vậy bạn cần đảm bảo rằng kích thước cấu trúc cuối cùng của bạn là bội số của 8 byte. Điều này có nghĩa là bạn có thể thêm 6 phần tử hoặc bạn có thể chọn loại dữ liệu lớn hơn.

Điều này có nghĩa bạn sẽ nhận được một cái gì đó như thế này:

typedef struct __attribute__((packed)) node { 
    struct node *next; 
    char data[8]; 
} nodea; 

typedef struct __attribute__((packed)) node { 
    struct node *next; 
    uint16_t data[4]; 
} nodea; 

typedef struct __attribute__((packed)) node { 
    struct node *next; 
    uint32_t data[2]; 
} nodea; 

vv vv vv

Các vấn đề liên quan