如何在跨文件预处理时获取唯一值

Sum*_*Roy 6 c embedded macros c-preprocessor

问题

我需要一种使用预处理器指令生成唯一值的方法.目的是每次调用宏时,它将具有唯一的整数标识符.但它应该保留它跨文件的价值.有点像预处理器计数器,用于调用函数的次数.

进一步的信息

我正在使用的宏是:

#define LOG_MSG(a) log_msg(?)
Run Code Online (Sandbox Code Playgroud)
  1. 'a'是用户想要打印的字符串.
  2. log_msg是一个用于在UART上打印消息的自定义函数
  3. '?' 如果我需要帮助的部分.

该宏仅在一个地方定义.在预处理阶段,'?' 将被唯一标识符替换.我们这样做是为了减少字符串带来的开销,因为此代码将在嵌入式设备上运行.在预处理之后,将提取标识符和相关字符串,并且将创建将映射它们的表(这将在应用程序侧).

由于这将用于多个文件,我想要一种方法来为多个文件中的每次使用生成唯一标识符(整数而不是字符串)(每个唯一字符串的标识符将是理想的但不是必需的).

有任何想法吗?

如果有任何遗漏或不完整的信息,请提及

笔记

__COUNTER__这是我尝试的第一件事,但它并不适用于文件.
__FILE__会给我一个破坏目的的字符串.

有人提到使用唯一文件标识符.但我不想静态分配这些.我们正在使用CCS(它基于Eclipse Kepler构建)来构建此代码.所以我想我们可以在构建系统中添加一些内容来执行@embedded_guy所提到的内容.谁知道怎么做?

谢谢

Dre*_*wen 5

通常,不可能确保始终为每个宏扩展生成唯一标识符.

您可以使用内置__LINE__宏来解决问题,假设每行最多使用一次宏.但是,由于您需要在多个文件中使用它,因此您需要手动定义另一个每个文件唯一的宏.例如,在foo.c的顶部:

#define FILE_NAME foo
#include "log.h" // or whatever defines `LOG_MSG`
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用宏连接FILE_NAME__LINE__生成唯一标识符.

如果只是一个字符串就足够了(而不是一个实际的变量),你也可以使用__FILE__宏,并结合__LINE__像这样的"stringized"版本:

#define FILE_LINE(x, y)  FILE_LINE_(x, y)
#define FILE_LINE_(x, y) x ## #y
#define LOG_UNIQUE_ID_STRING FILE_LINE(__FILE__, __LINE__)
Run Code Online (Sandbox Code Playgroud)

同样,这假定每个逻辑行最多一次调用.

一些编译器也支持一个__COUNTER__宏,可以代替它使用__LINE__,它允许每个逻辑行进行多次调用(但同样,你需要将它与其他东西结合起来,因为__COUNTER__在多个翻译单元(也就是C文件)中并不是唯一的) .


Cli*_*ord 4

我建议您的解决方案无法使用标准 C 预处理器来实现,并且需要不同的解决方案。此外,所提出的解决方案是不完整的 - 单独生成 UID 是不够的,您需要能够将该 UID 与原始字符串相关联,并且尚不清楚如何实现这一点。

编写一个单独的自定义预处理器似乎会更简单,该预处理器在源中搜索 的实例LOG_MSG( <some_string> ),提取<some string>它并用预处理器生成的 UID 替换它,并构建一个字符串表以供主机使用。

宏定义将是:

#define LOG_MSG(a) log_msg( a )
Run Code Online (Sandbox Code Playgroud)

但是,虽然在原始的未预处理代码中将a是一个文字字符串,但 log_msg() 将被定义log_msg( int a )

然后,在正确编译之前,执行预处理器将是必要的预构建步骤。大多数 IDE 支持可用于集成此工具的预构建和预编译步骤,或者添加为 make 规则,这很简单。

任何编译未预处理代码的尝试都将无法编译,因为参数将是字符串文字而不是整数,因此不存在省略执行预处理的危险。

您需要确保的唯一一件事是您在主机上使用与目标代码的特定构建相关联的字符串表 - 但无论如何您都会遇到这个问题。

请注意,它仅在 是文字字符串时才有效a- 但无论如何,最初提出的解决方案都是如此。您的预处理器可以检查这一点,并在未传递文字字符串时发出错误。