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

问题

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

更进一步的信息

我正在使用的宏是:

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

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

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

有任何想法吗?

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

笔记

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

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

谢谢

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

看起来编写一个单独的自定义预处理器会更简单,它会在源代码中搜索LOG_MSG( )实例,提取并用预处理器生成的UID替换它,并构建一个字符串表供以供使用主人。

宏定义将是:

 #define LOG_MSG(a) log_msg( a ) 

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

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

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

您需要确保的唯一事情是您在主机上使用与目标代码的特定构建相关联的字符串表 – 但在任何情况下您都遇到了这个问题。

请注意,它仅在a是文字字符串时才起作用 – 但在任何情况下都是最初提出的解决方案的情况。 您的预处理器可以检查并发出错误是没有传递文字字符串。

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

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

 #define FILE_NAME foo #include "log.h" // or whatever defines `LOG_MSG` 

然后,您可以在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__) 

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

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

虽然滥用预处理器指令,但您可以生成此处提到的伪随机数,并与另一个宏(如__FILE____LINE__ ,以生成唯一的字符串。

__COUNTER__是这样做的简单但非标准的方式。

Boost预处理器库也很有用。 例如,以下“ myheader.h ”头文件将在包含它的任何位置输出唯一标签。

 #include  #include  #if !defined(MYUNIQID) #define MYUNIQID #define BOOST_PP_VALUE 1 #include BOOST_PP_ASSIGN_SLOT(1) #undef BOOST_PP_VALUE #else #define BOOST_PP_VALUE BOOST_PP_INC(BOOST_PP_SLOT(1)) #include BOOST_PP_ASSIGN_SLOT(1) #undef BOOST_PP_VALUE #endif BOOST_PP_CAT(__FILE__, BOOST_PP_SLOT(1)): 

无论你在哪里#include "myheader.h"你的唯一ID都会生成。

为什么不试试#line预处理器指令呢? 您可以为每个源文件指定唯一的起始行号,然后使用__LINE__作为唯一标识符。 您必须确保在每个文件之间保留足够的行,以便所有数字保持唯一。 这是一个例子:

file_identifiers.h

 /* Maintain 10,000 lines between each file. If a file has greater than 10,000 lines then these numbers will have to be increased. */ #define FILE_IDENTIFIER_MAIN 10000 #define FILE_IDENTIFIER_LOG 20000 

log.h

 #include  void log_msg (int32_t unique_id); void log_test (void); 

log.c

 #include  #include "log.h" #include "file_identifiers.h" #line FILE_IDENTIFIER_LOG //log.c now starts with line 20000 void log_msg (int32_t unique_id) { printf("Unique ID: %d\r\n", unique_id); } void log_test (void) { log_msg(__LINE__); } 

main.c中

 #include  #include "file_identifiers.h" #include "log.h" #line FILE_IDENTIFIER_MAIN //main.c now starts with line 10000 int main (void) { log_msg(__LINE__); log_test(); exit (EXIT_SUCCESS); } 

OUTPUT

 Unique ID: 10003 Unique ID: 20008