2016-03-27 75 views
0

我用這個語句現在小,稍微更廣泛的錯誤消息之間在我Ç代碼切換:C預處理器的宏替換的#if #else僞陳述

#ifdef COMPACTC 
    error_code ((uint16_t) init_cascade, 5); 
#else 
    error_message (__func__, "cascades malloc failed"); 
#endif 

(嵌入式它的一部分C代碼庫,所以我經常沒有可用的內存來存儲錯誤消息字符串)。

在第一種情況下(COMPACTC定義),我只輸出函數地址和錯誤編號。在第二種情況下,我輸出完整的函數名稱和一個人類可讀的錯誤消息。

由於我現在複製這個片段都在我的代碼,我希望我能有一個宏觀的,我可以用這樣的替換:

error (init_cascade, "cascades malloc failed", 5) 

並提供正確的Ç代碼取決於是否定義COMPACTC。

也許這甚至有可能在當前函數(或某些唯一標識符)從當前位置自動導出,但我認爲預處理不知道這是目前在該函數的範圍。

另一個改進是如果可以從錯誤消息中自動生成一個唯一的錯誤代碼(本例中爲5,基於返回值)(如散列值或其他)。

然後宏調用可能是如此簡單:

error ("cascades malloc failed") 

當然,使用哈希值的時候,我需要某種形式的引用(文件/註釋),以它的原始郵件。

語境:在AVR 8位MCU

關於這個問題的背景下錯誤信息:此代碼爲ATmega168的(僅具有RAM 2K)編寫的,據我所知有沒有好/最近模擬器適用於Linux。所以我試圖找到一個很好的方式來產生錯誤消息/代碼,而不會讓字符串吃掉我所有的內存。

替代方案:C函數?

一個完全不同的,可能更靈活的解決方案是定義一個C函數error (function, message, code)並將#if/#else/#endif結構移動到它的主體。 我不確定是否字符串文字是由gcc編譯的,如果它在函數調用中被引用,但從未在函數體內使用。

編輯:我只是測試這個想法:使用字符串文字的呼叫,但不能在體內仍然有它添加到由GCC可執行文件,所以這個「另類」似乎並沒有工作。

+1

對於功能名字你可以使用'__FUNCTION__',並且對於一個有點獨特的ID你可以使用'__LINE__' – Dani

回答

2

這實際上應該是相當容易:

#ifdef COMPACTC 
# define COMBINED_ERROR(function, message, size) error_code((uint16_t)function, size) 
#else 
# define COMBINED_ERROR(function, message, size) error_message (__func__, message) 
#endif 

,現在你可以這樣寫:

COMBINED_ERROR(init_cascade, "cascades malloc failed", 5); 
0

在第一部分,我建議:

#ifdef COMPACTC 
# define error(par1, ...) error_code((uint16_t)par1, __VA_ARGS__) 
#else 
# define error(par1, ...) error_message (__func__, par1, __VA_ARGS__) 
#endif 

有了這個解決方案,您可以根據你的喜好定義許多參數。
對於第二個要求,考慮使用宏來插入特定的代碼。請看下面的宏:

#define CallWithError(fnc, ...) { \ 
            int RetCode = fnc(__VA_ARGS__); \ 
            if (RetCode) \ 
             error(init_cascade, "cascades malloc failed", RetCode); \ 
           } 

在這種情況下,你可以使用宏調用函數foo,並自動生成錯誤:

CallWithError(foo, 1, "hello"); 

這將擴大:

{ 
    int RetCode = foo(1, "hello"); 
    if (RetCode) 
     error(init_cascade, "cascades malloc failed", RetCode); 
}