2016-03-27 40 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); 
}