我需要一种使用预处理器指令生成唯一值的方法。目的是每次调用宏时,它都会有一个唯一的整数标识符。但它应该保留它跨文件的价值。有点像预处理器计数器,用于调用函数的次数。
我使用的宏是:
#define LOG_MSG(a) log_msg(?)
此宏仅在一个地方定义。在预处理阶段,'?'将被唯一标识符替换。我们这样做是为了减少字符串带来的开销,因为此代码将在嵌入式设备上运行。在预处理之后,将提取标识符和相关字符串,并创建一个将映射它们的表(这将在应用程序端)。
由于这将用于多个文件,我想要一种方法来为多个文件中的每次使用生成唯一标识符(整数而不是字符串)(每个唯一字符串的标识符将是理想的但没必要。)
有什么想法吗?
如果有任何遗漏或不完整的信息,请提及
备注
__COUNTER__
是我尝试的第一件事,但它不适用于文件
__FILE__
会给我一个违背目的的字符串。
有人提到使用唯一文件标识符。但我不想静态分配这些。我们正在使用CCS(它基于Eclipse Kepler构建)来构建此代码。所以我想我们可以在构建系统中添加一些内容来执行@embedded_guy所提到的内容。有谁知道怎么做?
由于
答案 0 :(得分:5)
通常,不可能确保始终为每个宏扩展生成唯一标识符。
您可以使用内置__LINE__
宏来解决问题,假设每行最多使用一次宏。但是,由于您需要在多个文件中使用它,因此您需要手动定义另一个每个文件唯一的宏。例如,在 foo.c 的顶部:
#define FILE_NAME foo
#include "log.h" // or whatever defines `LOG_MSG`
然后,您可以在FILE_NAME
和__LINE__
上使用宏连接来生成唯一标识符。
如果只是一个字符串就足够了(而不是实际的变量),你也可以使用__FILE__
宏,并结合__LINE__
的“字符串化”版本,如下所示:
#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文件)中并不是唯一的。)
答案 1 :(得分:4)
我建议使用标准C预处理器无法实现您的解决方案,并且需要不同的解决方案。此外,建议的解决方案还不完整 - 单独生成UID是不够的,您需要能够将该UID与原始字符串相关联,并且不清楚如何实现该目标。
编写一个单独的自定义预处理器似乎更简单,该预处理器在源代码中搜索LOG_MSG( <some_string> )
的实例,提取<some string>
并用预处理器生成的UID替换它,并构建一个字符串表供主人使用。
宏定义将是:
#define LOG_MSG(a) log_msg( a )
但是,在原始的未经预处理的代码中,a
将是一个文字字符串,而log_msg()将被定义为log_msg( int a )
。
在编译之前,执行预处理器将是必要的预构建步骤。大多数IDE支持可用于集成此工具的预构建和预编译步骤,或者作为make规则添加例如足够简单。
任何编译未经过预处理的代码的尝试都将无法编译,因为参数将是字符串文字而不是整数,因此不存在省略执行预处理的危险。
您唯一需要确保的是,您在主机上使用与目标代码的特定构建相关联的字符串表 - 但无论如何您都遇到了这个问题。
请注意,它仅在a
是文字字符串时才有效 - 但在任何情况下都是最初提出的解决方案的情况。您的预处理器可以检查并发出错误,但未传递文字字符串。
答案 2 :(得分:1)
虽然它滥用了预处理器指令,但您可以生成here提到的伪随机数,并与另一个宏__FILE__
或__LINE__
连接,以生成唯一字符串。
__COUNTER__
是一种简单但非标准的做法。
Boost Preprocessor library也很有用。例如,以下“myheader.h
”头文件将在包含它的任何位置输出唯一标签。
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/slot/slot.hpp>
#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)):
您的唯一ID将在#include "myheader.h"
答案 3 :(得分:1)
为什么不试试#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 <stdint.h>
void log_msg (int32_t unique_id);
void log_test (void);
<强> log.c 强>
#include <stdio.h>
#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 <stdlib.h>
#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);
}
<强>输出强>
Unique ID: 10003
Unique ID: 20008