我创建C ++中的宏声明一个变量和一些值分配给它。 根据宏是如何使用的,宏观的第二次出现可以覆盖所述第一变量的值。 例如:
#define MY_MACRO int my_variable_[random-number-here] = getCurrentTime();
其他动机的是使用以避免选择特定名称的变量,以便它是相同的最终通过使用宏开发人员选择一个名称。
有没有一种方法来生成C ++中的宏中随机变量的名字呢?
- 编辑 -
我的意思是独一无二的,但也是随机的,一旦我能在一个块,在这种情况下,它会产生类似于用我的宏两次:
int unique_variable_name;
...
int unique_variable_name;
在这种情况下,是唯一的两个变量名必须是随机生成的。
Answer 1:
加入M4到您的构建流程? 这个宏语言有一些状态的能力,并能成功地与CPP宏混杂。 这可能不是在C环境下生成唯一名称的标准方式,虽然我已经能够以这样的方式成功地使用它。
你可能不不想随机的,顺便说一下,根据你提出你的问题的方式。 你想要独一无二的 。
您可以使用__FILE__
和__LINE__
宏扩展,让你的独特性,你似乎是想为......那些元变量获取源文件的上下文中定义的,所以一定要小心,以确保你得到你所期待的,如(,多个宏的在同一行上危险)。
Answer 2:
尝试以下方法:
// This is some crazy magic that helps produce __BASE__247
// Vanilla interpolation of __BASE__##__LINE__ would produce __BASE____LINE__
// I still can't figure out why it works, but it has to do with macro resolution ordering
#define PP_CAT(a, b) PP_CAT_I(a, b)
#define PP_CAT_I(a, b) PP_CAT_II(~, a ## b)
#define PP_CAT_II(p, res) res
#define UNIQUE_NAME(base) PP_CAT(base, __COUNTER__)
__COUNTER__
据传有便携性的问题。 如果是这样,你可以使用__LINE__
,而不是只要你不是要求比每行或共享跨编译单元的名称一旦宏越多,你会就好了。
Answer 3:
使用__COUNTER__
(作品上gcc4.8,铛3.5和英特尔的icc V13,MSVC 2015年)
#define CONCAT_(x,y) x##y
#define CONCAT(x,y) CONCAT_(x,y)
#define uniquename static bool CONCAT(sb_, __COUNTER__) = false
Answer 4:
在预处理器生成唯一的名称是困难的。 你可以得到的最接近的是裂伤__FILE__
和__LINE__
到符号作为POPCNT建议。 如果你真的需要生成唯一的全局符号名称,那么我会按照有关使用类似M4或Perl脚本在构建系统,而不是他的建议。
您可能不需要唯一的名称。 如果您的宏可以强加一个新的范围,那么你可以使用相同的名称,因为它只会遮蔽其他定义。 我通常遵循包装宏在共同建议do { ... } while (0)
循环。 这仅适用于宏这是一个声明 - 不表达。 宏可以更新使用输出参数变量。 例如:
#define CALC_TIME_SINCE(t0, OUT) do { \
std::time_t _tNow = std::time(NULL); \
(OUT) = _tNow - (t0); \
} while (0)
如果你遵循一些规则 ,你通常是很安全:
- 使用前导下划线或类似的约定对宏内定义的符号。 这将阻止使用相同的符号,从发生的参数相关的问题。
- 仅使用输入参数一次,并始终围绕它们的括号。 这是为了与表达式作为输入宏的工作的唯一办法。
- 使用
do { ... } while (0)
成语,以确保宏仅用作陈述,并避免其他文本替换问题。
Answer 5:
相反,具有预处理程序创建一个名字,你可能让宏用户给你一个名字。
#define MY_MACRO(varname) int varname = getCurrentTime();
Answer 6:
我需要的,我没有任何分析工具的情况下,类似的东西,但我想算多少线程是一个特定的代码块,以及的时间量内(蜱)的代码块花了各线程,在这种情况下每个块需要一个唯一的静态变量所有可访问的线程,我需要后来引用该变量增量(我用了一个日志API,而不是printf的实际代码,但这个工程,以及)。 起初我还以为我是通过以下操作非常巧妙:
#define PROF_START { \
static volatile int entry_count##___FUNCTION__##__LINE__ = 0; int *ptc = &entry_count##___FUNCTION__##__LINE__; \
clock_t start, end; \
start = times(0); \
(*ptc)++;
但后来我意识到,这仅仅是愚蠢和C编译器将只为你做这个,只要每一个“静态”的声明是自己的块:
#include <stdio.h>
#include <sys/times.h>
#define PROF_START { \
static int entry_count = 0; \
clock_t start, end; \
start = times(0); \
entry_count++;
#define PROF_END \
end = times(0); \
printf("[%s:%d] TIMER: %ld:%d\n" , __FUNCTION__, __LINE__, end-start, entry_count); \
entry_count--; \
}
注意每个宏开/关括号。 这不是严格的线程安全的,但我的分析目的,我可以承担增量和DECR操作是原子的。 下面是它采用了宏的递归样本
#define ITEM_COUNT 5
struct node {
int data;
struct node *next;
};
revsort(struct node **head)
{
struct node *current = *head;
struct node *next_item;
while (current->next)
{
PROF_START
next_item = current->next;
current->next = next_item->next;
next_item->next = *head;
*head = next_item;
PROF_END
}
}
rrevsort(struct node **head)
{
struct node *current = *head;
struct node *next_item = current->next;
PROF_START
current->next = 0;
if (next_item)
{
*head = next_item;
rrevsort(head);
next_item->next = current;
}
PROF_END
}
printnode(struct node *head)
{
if (head)
{
printf("%d ", head->data);
printnode(head->next);
}
else
printf("\n");
}
main()
{
struct node node_list[ITEM_COUNT];
struct node *head = &node_list[0];
int i;
for (i=0; i < ITEM_COUNT - 1; i++)
{
PROF_START
node_list[i].data = i;
node_list[i].next = &node_list[i+1];
PROF_END
}
node_list[i].data = i;
node_list[i].next = 0;
printf("before\n");
printnode(head);
revsort(&head);
printf("after\n");
printnode(head);
rrevsort(&head);
printf("before\n");
printnode(head);
}
额外的提示,上面的程序是一种常见的面试问题。 从“纳米-A”摘录:
macro:0804a034 b entry_count.1715
macro:0804a030 b entry_count.1739
macro:0804a028 b entry_count.1768
macro:0804a02c b entry_count.1775
Answer 7:
这里是一个简洁的宏定义,以产生上述的单例模式。
#define SINGLETON_IMPLIMENTATION(CLASS_NAME) static CLASS_NAME *g##CLASS_NAME = nil; + (CLASS_NAME *)instance { @synchronized(self) { if (g##CLASS_NAME == nil) g##CLASS_NAME = [self new]; } return g##CLASS_NAME; }
#define SINGLETON_DECLARATION(CLASS_NAME) + (CLASS_NAME *)instance;
Answer 8:
虽然我不认为它甚至有可能,你应该认真考虑制定类出于此。
如果你想在一个随机排列的随机元件可以保持一定的值,你可以这样做:
std::vector< std::vector<int> > m_vec;
然后把它包在一个类,因此开发者只能设置一个数字:
void set(int foo)
{
m_vec[random()][random()] = foo;
}
是否有任何理由,你为什么想要它的宏? 随机变量的名字听起来很危险的,如果它挑选的东西已经在代码中定义别的地方?
文章来源: How to generate random variable names in C++ using macros?