2014-02-14 65 views
0

我目前正在嘗試對結構數組執行編譯時檢查,以確保如果有人在將來更改它,數組的每個元素都被定義。我想避免某個人向結構數組中添加太多元素的情況,如果我明確設置數組大小,這可能是可能的。這並不包括某人在數組中定義了太少元素的情況,其餘元素只是零初始化。C預定義錯誤檢查定義數組元素

#include <stdio.h> 

typedef struct myStruct { 
    int a; 
    int b; 
} myStruct_t; 

#define ARRAY_SIZE (3) 

myStruct_t sArr[] = { 
    {0, 0}, 
    {1, 1}, 
    {2, 2} 
} 

#define RATIO  (sizeof(sArr)/sizeof(myStruct_t)) 
#if ARRAY_SIZE != RATIO 
#error API issue 
#endif 

int main(void) { 
    printf("Testing\n"); 
    return 0; 
} 

這似乎是一個聲音檢查,因爲sizeof()是在編譯時評估。但是編譯器報告:

test.c:15:12: error: missing binary operator before token "(" 
test.c:19: error: expected ',' or ';' before 'int' 

如果可能,我該如何執行這樣的檢查?

謝謝。

+3

'}'關閉'sArr'聲明後需要分號。 – TypeIA

+0

#define RATIO(sizeof(sArr)/ sizeof(myStruct_t))在編譯時得到擴展但未被評估... –

回答

2

您必須在預處理階段之後使用編譯器的功能。

C11具有_Static_assert

_Static_assert(ARRAY_SIZE == RATIO); 

這將是最乾淨的解決方案。如果你沒有,如果比較結果爲1這是一個有效的typedef,將不需要做任何事情,你可以使用的技巧,比如

typedef char something_useless[ARRAY_SIZE == RATIO]; 

。如果是0並且會發生錯誤(違反約束)。

1

預處理器不計算sizeof()。這是由編譯器完成的。編譯C程序有兩個主要階段,即只進行文本轉換的預處理器階段和編譯預處理器輸出的第二個主要階段。

這意味着C語言變量和結構體不會被預處理程序評估,因此您的決定不會奏效。

您可以考慮使用ASSERT()宏來聲明特定的條件。如果ASSERT()已啓用以展開ASSERT()宏,則會在運行時評估這些值。

我實際上編寫了自己的版本,將特定的斷言放入一些函數中,以對結構的大小執行運行時檢查。有了我自己的assert宏,我可以選擇性地打開和關閉它們。

使用我自己的斷言宏,我有一個函數可以創建斷言的日誌,如果構建是一個調試構建,比如正在用於設計器測試,函數將執行一箇中斷,以便設計器將看到立即斷言失敗並能夠執行堆棧跟蹤並採取其他步驟來確定斷言發生的原因。

的基本側傾我用自己的斷言宏:

#define NHPOS_ASSERT(x) if (!(x)) { PifLogAbort((UCHAR *) #x , (UCHAR *) __FILE__ , (UCHAR *) "function" , __LINE__);} 

其中PifLogAbort()是生成的日誌文件的功能。使用這個我可以看到與文件名和行號一起聲明的條件。