如何禁用C中的結構填充而不使用雜注?在不使用雜注的情況下禁用C中的結構填充
回答
實現沒有標準這樣做的方式。該標準規定填充可以根據實現的意願進行。來自C99 6.7.2.1 Structure and union specifiers
,第12段:
結構體或聯合體對象的每個非位字段成員都以適合其類型的實現定義的方式對齊。
說了這麼多,你可以嘗試幾件事情。
您第一次四折,用#pragma
,試圖說服編譯器不收拾。無論如何,這不是便攜式的。也沒有任何其他特定於實現的方法,但是您應該檢查它們,因爲如果您確實需要此功能,可能需要執行此操作。
二是從最大到最小,以訂購您的領域,如所有long long
類型其次long
的,那麼所有的int
,short
最後char
類型。這通常會起作用,因爲它通常是具有更嚴格對齊要求的較大類型。再次,不便攜式。
第三,你可以定義你的類型,char
陣列和投的地址,以確保沒有填充。但請記住,如果變量未正確對齊,某些體系結構將放慢速度,而其他體系結構將會失敗(例如,引發BUS錯誤並終止您的過程)。
最後一個有一些進一步的解釋。假設你有以下順序的字段的結構:
char C; // one byte
int I; // two bytes
long L; // four bytes
隨着填充,你可以用下面的字節結束:
CxxxIIxxLLLL
其中x
是填充。
但是,如果你定義了你的結構爲:
typedef struct { char c[7]; } myType;
myType n;
你:
CCCCCCC
然後,您可以這樣做:
int *pInt = &(n.c[1]);
int *pLng = &(n.c[3]);
int myInt = *pInt;
int myLong = *pLng;
給你:
CIILLLL
不幸的是,不能攜帶。
所有這些「解決方案」都依賴於您熟悉編譯器和底層數據類型。
除了像編譯指示包這樣的編譯選項以外,不能在C標準中填充填充。
你總是可以嘗試通過在結構最後宣佈最小的類型,在減少填充:
struct _foo {
int a; /* No padding between a & b */
short b;
} foo;
struct _bar {
short b; /* 2 bytes of padding between a & b */
int a;
} bar;
注對於具有4個字節邊界
在某些體系結構上,如果系統要求處理未對齊的數據,CPU本身會反對。要解決這個問題,編譯器可以生成多個對齊的讀或寫指令,移位和分割或合併各個位。您可以合理地預期它比對齊的數據處理慢5到10倍。但是,該標準並不要求編譯器做好準備......考慮到性能成本,它只是沒有足夠的需求。支持顯式控制填充的編譯器提供了它們自己的編譯指示,這是因爲編譯指示保留用於非標準功能。
如果您必須使用未打底數據,請考慮編寫您自己的訪問例程。您可能想要嘗試使用較少對齊的類型(例如,使用char/int8_t),但仍有可能例如結構的大小將被四捨五入爲4的倍數,這會嚴重阻礙打包結構,在這種情況下,您需要實現對整個內存區域的訪問。
要麼讓編譯器進行填充,要麼告訴它不要使用#pragma,要麼就像使用char數組一樣使用一些字節,並且自己構建所有數據(移位和添加字節)。這實際上效率很低,但你會精確控制字節的佈局。我曾經這樣做過,有時手動準備網絡數據包,但在大多數情況下,這是一個壞主意,即使它是標準的。
如果您確實需要不帶填充的結構:使用僅由8位字節組成的結構或類來定義short,int,long等的替換數據類型。然後使用替換數據類型編寫更高級別的結構。
C++的操作符重載非常方便,但是您可以在C中使用結構而不是類實現相同的效果。下面的轉換和賦值實現假定CPU可以處理未對齊的32位整數,但其他實現可以容納更嚴格的CPU。
下面是示例代碼:
#include <stdint.h>
#include <stdio.h>
class packable_int { public:
int8_t b[4];
operator int32_t() const { return *(int32_t*) b; }
void operator = (int32_t n) { *(int32_t*) b = n; }
};
struct SA {
int8_t c;
int32_t n;
} sa;
struct SB {
int8_t c;
packable_int n;
} sb;
int main() {
printf ("sizeof sa %d\n", sizeof sa); // sizeof sa 8
printf ("sizeof sb %d\n", sizeof sb); // sizeof sb 5
return 0;
}
我們所用的C程序使用以下方法中的任何一個禁用結構填充。
- >使用__attribute__((packed))
定義結構。例如。
struct node {
char x;
short y;
int z;
} __attribute__((packed));
- >在編譯c代碼時使用-fpack-struct
標誌。例如。
$ gcc -fpack-struct -o tmp tmp.c
希望這會有所幫助。 謝謝。
- 1. 填充結構內存使用情況
- 2. 在不使用填充句柄的情況下在Excel中填充列
- 3. C++中的結構填充
- 4. 在不調用setContentView的情況下填充listview
- 5. 如何在已經漂浮的情況下使用填充權?
- 6. 遞歸填充樹視圖(複雜的情況下)
- 7. 在不使用主鍵的情況下填充js中的一對多關係
- 8. 在不禁用HBASE表的情況下更改表結構的含義
- 9. 關於在C++中的結構填充
- 10. 使用memcpy填充結構
- 11. 使用snprintf填充結構
- 12. 如何在不使用STL的情況下實現C++字典數據結構
- 13. 用兩個級別數組c填充複雜結構#
- 14. 如何在不使用兩個for-loops的情況下填充我的data.table?
- 15. 如何在C#中不使用Edmx的情況下使用DbContext?
- 16. 不使用結構數組填充tableview
- 17. 是否可以在不禁用JavaScript的情況下禁用AJAX?
- 18. 在不禁用uibuttons的情況下在uiscrollview中啓用backgroundTap
- 19. 如何在不增加div大小的情況下在HTML中應用填充?
- 20. 在不削波的情況下填充CGPath的反函數
- 21. JSF如何在不使用會話範圍的情況下填充新頁面?
- 22. 如何讓div在不使用浮動的情況下填充剩餘空間?
- 23. 如何在不使用表單的情況下填充數據庫/模型?
- 24. 在不使用表格的情況下將iframe填充到屏幕底部
- 25. 如何在不填充角落的情況下填充一個numpy數組?
- 26. 在不使用全局變量的情況下GAE中的結構數據流
- 27. 如何在默認情況下填充自動填充?
- 28. 如何在不使用複雜代碼結構的情況下連接Java中的字符串?
- 29. 使Ant在不同情況下使用不同的構建類?
- 30. 在我的情況下使用什麼數據結構?
這是非標準的。是否可能(以及如何)這完全取決於你正在使用哪種C實現。 – 2010-11-29 07:47:50
我認爲沒有其他辦法可以做到這一點。 – frast 2010-11-29 07:48:36