生成函数和全局变量

时间:2013-12-17 01:27:05

标签: c sqlite macros c-preprocessor

我想知道是否有办法将 C 预处理器用于这样的事情。我有一个包含大量SQL语句的代码,我想在启动时准备,然后只保留全局变量。我试图想出一种方法来编写一个可以转换的宏:

PREPARE_SQL (statement1_var, "SQL QUERY 1")
PREPARE_SQL (statement2_var, "SQL QUERY 2")

成:

static sqlite3_stmt * statement1_var;
static sqlite3_stmt * statement2_var;

static int prepare_statements(sqlite3 * db) {
    int result;

    result = sqlite3_prepare_v2(db, "SQL QUERY 1", -1, &statement1_var, NULL);
    if (result != SQLITE_OK) {
        return result;
    }
    result = sqlite3_prepare_v2(db, "SQL QUERY 2", -1, &statement2_var, NULL);
    if (result != SQLITE_OK) {
        return result;
    }
    return SQLITE_OK;
}

2 个答案:

答案 0 :(得分:1)

使用X宏技术,首先使用尚未定义的宏PREPARE_SQL

定义列表
#define LIST_OF_ENTRIES                       \
PREPARE_SQL (statement1_var, "SQL QUERY 1")   \
PREPARE_SQL (statement2_var, "SQL QUERY 2")

然后定义PREPARE_SQL以声明变量,调用列表宏,然后再次取消定义PREPARE_SQL

#define PREPARE_SQL( var, text ) static sqlite3_stmt * var;
LIST_OF_ENTRIES        // invoke the macro that contains the list
#undef PREPARE_SQL

然后,再次重新定义PREPARE_SQL,并调用相同的列表宏...

static int prepare_statements(sqlite3 * db) {
    int result;

#define PREPARE_SQL(var, text)                               \
    result = sqlite3_prepare_v2(db, text, -1, &var, NULL);   \
    if (result != SQLITE_OK) {                               \
        return result;                                       \
    }
    LIST_OF_ENTRIES   // invoke the macro that contains the list
#undef PREPARE_SQL

    return SQLITE_OK;
}

答案 1 :(得分:0)

这是一种方法。它需要两个宏,但我认为它接近你想要的。

宏:

#define PREPARE_SQL_DECLARATION(V) static sqlite3_stmt *(V);

#define PREPARE_SQL(V,Q) \
    do { \
        int result = sqlite3_prepare_v2(db, (Q), -1, &(V), NULL); \
        if (result != SQLITE_OK) \
            return result; \
    } while(0);

宏的示例用法(例如source.c

PREPARE_SQL_DECLARATION(statement1_var);
PREPARE_SQL_DECLARATION(statement2_var);
PREPARE_SQL_DECLARATION(statement3_var);

static int prepare_statements(sqlite3 * db) {
    PREPARE_SQL(statement1_var, "SQL QUERY 1");
    PREPARE_SQL(statement2_var, "SQL QUERY 2");
    PREPARE_SQL(statement3_var, "SQL QUERY 3");
    return SQLITE_OK;
}

以下是宏扩展的输出(例如gcc -E source.c

static sqlite3_stmt *(statement1_var);;
static sqlite3_stmt *(statement2_var);;
static sqlite3_stmt *(statement3_var);;

static int prepare_statements(sqlite3 * db) {
    do { int result = sqlite3_prepare_v2(db, ("SQL QUERY 1"), -1, &(statement1_var), 0); if (result != 0) return result; } while(0);;
    do { int result = sqlite3_prepare_v2(db, ("SQL QUERY 2"), -1, &(statement2_var), 0); if (result != 0) return result; } while(0);;
    do { int result = sqlite3_prepare_v2(db, ("SQL QUERY 3"), -1, &(statement3_var), 0); if (result != 0) return result; } while(0);;
    return 0;
}

在宏中包装代码的do { ... } while (0);是每个语句扩展和执行的一种方式,可以在范围内返回自己的int result,但不会干扰后面的同名变量。< / p>

希望这有帮助。