命题 1:X 宏
可以使用Linux内核源代码中广泛使用的X macros的概念。这个想法是提供一个名为X的宏的多个扩展:
#include <stdio.h>
// The X-macro
#define LIST_OF_ERRORS \
X(ERROR_MSG_1, "Failed to open file.\n") \
X(ERROR_MSG_2, "Failed to read file.\n") \
X(ERROR_MSG_3, "Failed to execute abc.\n")
// 1st definition of X to define enum error codes
#define X(e, m) e,
enum {
LIST_OF_ERRORS
};
#undef X
// 2nd definition of X to define cases in a switch
void print_error(int e)
{
#define X(e, m) case e: printf("[ERROR] : code (%d)\n\t%s", e, m); break;
switch(e) {
LIST_OF_ERRORS
default: printf("[ERROR] : unknown code (%d)\n", e);
}
#undef X
}
int main(void)
{
print_error(ERROR_MSG_2);
print_error(ERROR_MSG_1);
print_error(ERROR_MSG_3);
print_error(10);
return 0;
}
测试:
$ gcc err.c
$ ./a.out
[ERROR] : code (1)
Failed to read file.
[ERROR] : code (0)
Failed to open file.
[ERROR] : code (2)
Failed to execute abc.
[ERROR] : unknown code (10)
注意:这部分回答了我使用多行宏的问题...
命题2:##运算符
在这个命题中,您需要使用“硬编码”常量错误号作为参数传递给PRINT_ERROR() 宏,否则编译器会报错。如果您传递未知的错误号,编译器也会报错。
#include <stdio.h>
#define ERROR_LABEL_0 "Error message#0\n"
#define ERROR_LABEL_1 "Error message#1\n"
#define ERROR_LABEL_2 "Error message#2\n"
#define ERROR_LABEL_3 "Error message#3\n"
#define PRINT_ERROR(e) fprintf(stderr, "[ERROR] : code (%d)\n\t%s", e, ERROR_LABEL_##e)
int main(void)
{
PRINT_ERROR(2);
PRINT_ERROR(1);
PRINT_ERROR(3);
return 0;
}
执行:
$ gcc macro.c
$ ./a.out
[ERROR] : code (2)
Error message#2
[ERROR] : code (1)
Error message#1
[ERROR] : code (3)
Error message#3
但是如果你使用超出范围的变量或常量,编译器会报错:
[...]
int main(void)
{
int err = 2;
PRINT_ERROR(2);
PRINT_ERROR(1);
PRINT_ERROR(3);
PRINT_ERROR(err); // <---- Compilation error
PRINT_ERROR(10); // <---- Compilation error
return 0;
}
编译器显示的错误:
$ gcc macro.c
macro.c: In function 'main':
macro.c:15:72: error: 'ERROR_LABEL_err' undeclared (first use in this function); did you mean 'ERROR_LABEL_1'?
15 | #define PRINT_ERROR(e) fprintf(stderr, "[ERROR] : code (%d)\n\t%s", e, ERROR_LABEL_##e)
| ^~~~~~~~~~~~
macro.c:25:3: note: in expansion of macro 'PRINT_ERROR'
25 | PRINT_ERROR(err); // <---- Compilation error
| ^~~~~~~~~~~
macro.c:15:72: note: each undeclared identifier is reported only once for each function it appears in
15 | #define PRINT_ERROR(e) fprintf(stderr, "[ERROR] : code (%d)\n\t%s", e, ERROR_LABEL_##e)
| ^~~~~~~~~~~~
macro.c:25:3: note: in expansion of macro 'PRINT_ERROR'
25 | PRINT_ERROR(err); // <---- Compilation error
| ^~~~~~~~~~~
macro.c:15:72: error: 'ERROR_LABEL_10' undeclared (first use in this function); did you mean 'ERROR_LABEL_1'?
15 | #define PRINT_ERROR(e) fprintf(stderr, "[ERROR] : code (%d)\n\t%s", e, ERROR_LABEL_##e)
| ^~~~~~~~~~~~
macro.c:26:3: note: in expansion of macro 'PRINT_ERROR'
26 | PRINT_ERROR(10); // <---- Compilation error