[英]C sizeof equivalent for macros
所以我通過展開一些循環來優化一些代碼(是的,我知道我應該依靠我的編譯器來為我做這個,但我不會選擇我的編譯器)並且我想這樣做有點優雅所以如果我的數據大小由於將來的一些編輯而發生變化,代碼將會優雅地降級。
就像是:
typedef struct {
uint32_t alpha;
uint32_t two;
uint32_t iii;
} Entry;
/*...*/
uint8_t * bytes = (uint8_t *) entry;
#define PROCESS_ENTRY(i) bytes[i] ^= 1; /*...etc, etc, */
#if (sizeof(Entry) == 12)
PROCESS_ENTRY( 0);PROCESS_ENTRY( 1);PROCESS_ENTRY( 2);
PROCESS_ENTRY( 3);PROCESS_ENTRY( 4);PROCESS_ENTRY( 5);
PROCESS_ENTRY( 6);PROCESS_ENTRY( 7);PROCESS_ENTRY( 8);
PROCESS_ENTRY( 9);PROCESS_ENTRY(10);PROCESS_ENTRY(11);
#else
# warning Using non-optimized code
size_t i;
for (i = 0; i < sizeof(Entry); i++)
{
PROCESS_ENTRY(i);
}
#endif
#undef PROCESS_ENTRY
當然,這不起作用,因為預處理器無法使用sizeof
(至少, 這個答案似乎表明了這一點 )。
是否有一個簡單的解決方法,我可以用來獲取與C宏一起使用的數據結構的sizeof
,或者我只是SOL?
你不能在預處理器中做到這一點,但你不需要。 只是產生一個普通的if
在您的宏:
#define PROCESS_ENTRY(i) bytes[i] ^= 1; /*...etc, etc, */
if (sizeof(Entry) == 12) {
PROCESS_ENTRY( 0);PROCESS_ENTRY( 1);PROCESS_ENTRY( 2);
PROCESS_ENTRY( 3);PROCESS_ENTRY( 4);PROCESS_ENTRY( 5);
PROCESS_ENTRY( 6);PROCESS_ENTRY( 7);PROCESS_ENTRY( 8);
PROCESS_ENTRY( 9);PROCESS_ENTRY(10);PROCESS_ENTRY(11);
} else {
size_t i;
for (i = 0; i < sizeof(Entry); i++) {
PROCESS_ENTRY(i);
}
}
sizeof
是一個常量表達式,將常量與常量進行比較也是不變的。 任何理智的C編譯器都會優化掉在編譯時始終為false的分支 - 常量折疊是最基本的優化之一。 但是你失去了#warning
。
如果您使用的是autoconf或其他構建配置系統,則可以在配置時檢查數據結構的大小並寫出標頭(如#define SIZEOF_Entry 12
)。 當然,當交叉編譯時,這會變得更復雜,但我假設你的構建和目標架構是相同的。
否則是的,你運氣不好。
你運氣不好 - 預處理器甚至不知道結構是什么,更不用說任何方法來計算它的大小了。
在這種情況下你可以#define一個常量,你知道結構的大小是什么,然后靜態斷言它實際上等於使用負大小數組技巧的大小。
你也可以嘗試if (sizeof(Entry) == 12)
,看看你的編譯器是否能夠在編譯時評估分支條件並刪除死代碼。 這不是一個大問題。
這可能沒有幫助,但如果您能夠在C ++中執行此操作,則可以使用模板使編譯器在編譯時調度到適當的循環:
template <std::size_t SizeOfEntry>
void process_entry_loop(...)
{
// ... the nonoptimized version of the loop
}
template <>
void process_entry_loop<12>(...)
{
// ... the optimized version of the loop
}
// ...
process_entry_loop<sizeof(Entry)>(...);
我想到了另外兩種方法 - 編寫一個小應用程序來編寫展開的循環,或者在Duff的設備上使用具有預期結構大小的變體。
如果您想要結構的最小可能大小(或將其與4字節邊界或其他任何對齊),則可以使用packed或aligned屬性。
在Visual C ++中,您可以使用#pragma pack ,在GCC中可以使用__attribute __((packed))和__attribute __((aligned(num-bytes))。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.