写了一段代码,我想实现宏里面拼接一个变量然后取得这个变量的值的效果,但是没有成功:
#define OB_FIRST_ROOT_TABLE_TID 21
#define OB_INVALID_ID INT_MAX
const char* OB_FIRST_ROOT_TABLE_TABLE_NAME = "__first_root_table";
struct TableBackupSQL
{
uint64_t table_id_;
const char* sql_;
const char * table_name_;
TableBackupSQL()
{
sql_ = NULL;
table_name_ = NULL;
table_id_ = OB_INVALID_ID;
}
TableBackupSQL(uint64_t table_id, const char* table_name, const char* sql)
{
sql_ = sql;
table_name_ = table_name;
table_id_ = table_id;
}
};
#define TABLE_BACKUP_(table_prefix, table_name)\
TableBackupSQL(table_prefix##_TID, table_prefix##_TABLE_NAME, "select * from "#table_name)
#define TABLE_BACKUP(table_prefix)\
TABLE_BACKUP_(table_prefix, table_prefix##_TABLE_NAME)
TableBackupSQL table_backup_list_[] =
{
TABLE_BACKUP(OB_FIRST_ROOT_TABLE)
};
int main(void)
{
for (int i = 0; i < sizeof(table_backup_list_)/sizeof(TableBackupSQL); i++)
{
TableBackupSQL& desc = table_backup_list_[i];
printf("%d, %s, %s\n", desc.table_id_, desc.table_name_, desc.sql_);
}
}
期望的结果是
21, __first_root_table, select * from __first_root_table
实际的结果是
21, __first_root_table, select * from OB_FIRST_ROOT_TABLE_TABLE_NAME
拼出来的OB_FIRST_ROOT_TABLE_TABLE_NAME没有被替换,当然有很多方法绕开。我试图两次展开宏但是没有成功,这个跟这里说的问题毕竟不是一个。不知道C++11里面有没有解决方法。
另外,我才发现一个struct直接赋值是C++11才允许的。比如:
TableBackupSQL table_backup_list_[] =
{
{21, "__first_root_table", "select * from __first_root_table"}
};
不加-std=c++0x或者 -std=gnu++0x的时候会报错。c语言支持。
后来发现我遗忘了一个事实,宏替换是发生在预编译期的,这时候都没有做语法词法分析,程序不知道一个变量应该如何替换,所以变量实际上没有被替换成值,这跟函数定义是不一样的。比如:
#define wrap(value) value
int a = 1;
int b = wrap(a);
我们用gcc打印展开之后的结果如下:
int a = 1; int b = a;这里是不会展开成 int b = 1;的。而连接符#的作用也只是把宏替换后的字面值加上引号,比如:
#define wrap(value) #value int a = 1; const char * b = wrap(a);展开结果是:
int a = 1;
const char * b = "a";
而连接符##的作用就更简单了,就是提供一个标示宏传入参数的作用,比如
#define wrap(value) a##value
int ab = 2;
int b = wrap(b);
如果不写##就变成了avalue,无法区分输入参数,如果写a(value)就会替换成a(b),如果写a value就会替换成a b,所以想替换成ab只能用##。
至于上面那个问题,如果我们table的名字都是宏定义的字符串,那就好办多了:
const char* OB_FIRST_ROOT_TABLE_TABLE_NAME = “_first_root_table”; #define TABLE_BACKUP(table_prefix, table_name)TableBackupSQL(table_prefix##_TID, table_prefix##_TABLE_NAME, "select * from " table_name)
感谢郁白师兄的指导。
PREVIOUSoctopress代码着色
NEXTgit远程分支和refs文件详解