【发布时间】:2016-03-26 22:59:57
【问题描述】:
我想找到一种方法让函数返回(具有特定值)调用它的函数。在C中可能吗?也许通过检查调用堆栈?
抽象例子:假设我们有两个函数
int called() {
if (some_check_fails()) {
/* here make caller() return -1 so "Hello world!\n" is not printed */
}
}
int caller() {
called();
printf("Hello world!\n");
return 0;
}
我正在寻找要放入 /* ... */ 部分的内容。
现实生活中的例子:我正在使用的代码是一个在 SQLite 文件中导出数据的函数。这意味着对 SQLite API 的大量调用需要每次检查它们的返回值。结果是一个看起来很糟糕而且太长的函数,就像这样if (resp_code != SQLITE_OK) 部分不断重复:
sqlite3 *db;
char *err_msg;
/* Open the database in read-write mode, create it if not exists yet */
int resp_code = sqlite3_open_v2(filename, &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
NULL);
if (resp_code != SQLITE_OK) {
fprintf(stderr, "SQLite error: cannot open database %s, %s\n", filename,
sqlite3_errmsg(db));
sqlite3_close(db);
return OMG_ERROR_HERE;
}
/* Create table */
char *query_table = "DROP TABLE IF EXISTS sometable; "
"CREATE TABLE sometable "
"(value int, data TEXT);";
resp_code = sqlite3_exec(db, query_table, 0, 0, &err_msg);
if (resp_code != SQLITE_OK) {
fprintf(stderr, "SQLite error: %s\n", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
return OMG_ERROR_HERE;
}
/* Prepare statement */
char *query = "INSERT INTO sometable VALUES (@i, @s);";
sqlite3_stmt *stmt;
resp_code = sqlite3_prepare_v2(db, query, 150, &stmt, NULL);
if (resp_code != SQLITE_OK) {
fprintf(stderr, "SQLite error: %s\n", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
return OMG_ERROR_HERE;
}
/* Start transaction */
resp_code = sqlite3_exec(db, "BEGIN TRANSACTION", 0, 0, &err_msg);
if (resp_code != SQLITE_OK) {
fprintf(stderr, "SQLite error: %s\n", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
return OMG_ERROR_HERE;
}
/* AND SO ON */
我想要的是这样的:
sqlite3 *db;
char *err_msg;
/* Open the database in read-write mode, create it if not exists yet */
int resp_code = sqlite3_open_v2(filename, &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
NULL);
return_this_function_if_not_ok(resp_code);
/* Create table */
char *query_table = "DROP TABLE IF EXISTS sometable; "
"CREATE TABLE sometable "
"(value int, data TEXT);";
resp_code = sqlite3_exec(db, query_table, 0, 0, &err_msg);
return_this_function_if_not_ok(resp_code);
/* Prepare statement */
char *query = "INSERT INTO sometable VALUES (@i, @s);";
sqlite3_stmt *stmt;
resp_code = sqlite3_prepare_v2(db, query, 150, &stmt, NULL);
return_this_function_if_not_ok(resp_code);
/* Start transaction */
resp_code = sqlite3_exec(db, "BEGIN TRANSACTION", 0, 0, &err_msg);
return_this_function_if_not_ok(resp_code);
/* AND SO ON */
编辑 2015-12-21:我选择FUZxxl's answer 是最好的,因为它是唯一真正回答我关于返回调用函数的问题的人。另一方面,chux's answer(基于Rowland Shaw's 和Ziffusion's)正在以我喜欢的方式解决我的SQLite 问题。
非常感谢大家!!
【问题讨论】:
-
您可以使用宏来让预处理器为您编写错误检查代码
-
是什么阻止你使用返回值?或者您是否正在寻找某种方法来创建动态回调?
-
如果你今天感觉特别受虐,你可以看看
setjmp和longjmp。 -
顺便说一句:这就是异常被发明来解决的问题。