【问题标题】:C preprocessor macro replacing #if #else statementsC 预处理器宏替换 #if #else 语句
【发布时间】:2016-03-27 18:12:00
【问题描述】:

我现在使用此语句在我的 C 代码中的小错误消息和稍微更广泛的错误消息之间切换:

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

(它是嵌入式 C 代码库的一部分,所以我经常没有可用的内存来存储错误消息字符串)。

在第一种情况下(COMPACTC 定义)我只输出一个函数地址和错误号。在第二种情况下,我输出完整的函数名称和人类可读的错误消息。

由于我现在将这个 sn-p 复制到我的代码中,我希望我可以用一个宏替换它,我可以像这样使用它:

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

并根据是否定义了 COMPACTC 来提供正确的 C 代码。

也许甚至可以从当前位置自动派生当前函数(或某些唯一标识符),尽管我认为预处理器不知道它当前位于哪个函数的范围内。

如果可以从错误消息(如哈希值或其他内容)中自动生成唯一的错误代码(在本例中为 5,它基于返回值),则另一个改进是。

那么宏调用就这么简单:

error ("cascades malloc failed")

当然,在使用哈希时,我需要对其原始消息进行某种引用(文件/注释)。

上下文:AVR 8 位 MCU 上的错误消息

关于这个问题的背景:这段代码是为 ATmega168(只有 2k 的 RAM)编写的,AFAIK 没有适用于 Linux 的好的/最近的模拟器。因此,我正在尝试找到一种生成错误消息/代码的好方法,而不会让字符串占用我所有的内存。

替代方案:C 函数?

一个完全不同的、可能更灵活的解决方案是定义一个 C 函数 error (function, message, code) 并将 #if/#else/#endif 构造移动到它的主体。 我不确定如果字符串文字在函数调用中被引用但从未在函数体内使用过,gcc 是否会编译它。

编辑:我刚刚测试了这个想法:在调用中使用字符串文字但不在正文中仍然有它被 gcc 添加到可执行文件中,所以这个“替代”似乎不起作用。

【问题讨论】:

  • 函数名可以使用__FUNCTION__ ,有些独特的id可以使用__LINE__

标签: c gcc macros c-preprocessor avr


【解决方案1】:

这实际上应该相当简单:

#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);

【讨论】:

    【解决方案2】:

    我建议第一部分:

    #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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-22
      • 1970-01-01
      • 2014-11-29
      • 2018-09-20
      • 1970-01-01
      • 1970-01-01
      • 2018-03-29
      相关资源
      最近更新 更多