我正在做一个大项目,我有很多errno宏。
我想为日志记录器编写一个辅助函数,将这些errno字符串化为字符串。我决定使用x-宏,但我得到编译错误
首先,代码是这样的:
// project_errno.h
#define PROJECT_ERR_KEY_FAILURE 12222
#define PROJECT_ERR_CIPHER_ZERO_PADDING 12345
#define PROJECT_ERR_FAILED_TO_SETUP_ENC_KEY 14004
我整理的方法如下:
- 在另一个文件中放置x-宏:
// project_errno.hx
PROJECT_ERR_FUNC(PROJECT_ERR_KEY_FAILURE) 12222
PROJECT_ERR_FUNC(PROJECT_ERR_CIPHER_ZERO_PADDING) 12345
PROJECT_ERR_FUNC(PROJECT_ERR_FAILED_TO_SETUP_ENC_KEY) 14004
- 然后我把它变成一个enum:
// project_errno.h
enum {
#define PROJECT_ERR_FUNC(name, value) name=value,
#include "project_errno.hx"
#undef PROJECT_ERR_FUNC
};
- 然后我添加了一个将被记录器使用的函数:
// logging.h (declaration) and (definition) logging.c
const char* stringify_errno(int errno) {
switch (errno) {
#define PROJECT_ERR_FUNC(name, value) case name: return #value ;
#include "project_errno.hx"
#undef PROJECT_ERR_FUNC
}
}
所以,看起来很好,但我不能让它编译,我得到以下编译错误:
project_errno.h:8:53: error: error: expected identifier before numeric constant
#define PROJECT_ERR_CIPHER_ZERO_PADDING 12345
^
..../project_errno.h:17:30: note: in definition of macro ‘PROJECT_ERR_FUNC’
#define PROJECT_ERR_FUNC(name, value) name=value,
^~~~
..../project_errno.hx:47:14: note: in expansion of macro ‘PROJECT_ERR_CIPHER_ZERO_PADDING ’PROJECT_ERR_FUNC(PROJECT_ERR_CIPHER_ZERO_PADDING, 12345)
project_errno.h:8:53: error: error: expected ‘}’ before numeric constant
#define PROJECT_ERR_CIPHER_ZERO_PADDING 12345
^
..../project_errno.h:17:30: note: in definition of macro ‘PROJECT_ERR_FUNC’
#define PROJECT_ERR_FUNC(name, value) name=value,
^~~~
..../project_errno.hx:47:14: note: in expansion of macro ‘PROJECT_ERR_CIPHER_ZERO_PADDING ’PROJECT_ERR_FUNC(PROJECT_ERR_CIPHER_ZERO_PADDING, 12345)
project_errno.h:8:53: error: expected unqualified-id before numeric constant
#define PROJECT_ERR_CIPHER_ZERO_PADDING 12345
^
..../project_errno.h:17:30: note: in definition of macro ‘PROJECT_ERR_FUNC’
#define PROJECT_ERR_FUNC(name, value) name=value,
^~~~
..../project_errno.hx:47:14: note: in expansion of macro ‘PROJECT_ERR_CIPHER_ZERO_PADDING ’PROJECT_ERR_FUNC(PROJECT_ERR_CIPHER_ZERO_PADDING, 12345)
^~~~~~~~~~~~~~~~~~~~~~~
In file included from ......../project_errno.h:20:1: error: expected declaration before ‘}’ token
};
^
..../project_errno.h:17:30: note: in definition of macro ‘PROJECT_ERR_FUNC’
#define PROJECT_ERR_FUNC(name, value) name=value,
^~~~
..../project_errno.hx:47:14: note: in expansion of macro ‘PROJECT_ERR_CIPHER_ZERO_PADDING ’PROJECT_ERR_FUNC(PROJECT_ERR_CIPHER_ZERO_PADDING, 12345)
^~~~~~~~~~~~~~~~~~~~~~~
我不明白为什么我得到这些错误(我得到相同的错误信息多次在同一编译会话),我希望你们能帮助我。此外,如果你有任何其他的解决方案来解决问题,我打算在第一个地方解决(使用errno宏和添加一个函数来字符串化那些errnos每当我添加一个errno到项目[在只有一个地方]),我很乐意听到它谢谢
我会遵循维基百科页面上关于X宏的配方:
实施X宏应用程序由两部分组成:
- 列表元素的定义。
- 扩展列表以生成声明或语句的片段。
列表是由宏或头文件(命名为
LIST
)定义的,它本身不生成代码,而仅仅由一系列调用宏(经典命名为X
)的元素数据组成。LIST
的每次展开之前都有X
的定义,其语法为列表元素。LIST
的调用为列表中的每个元素展开X
。
特别是第二个例子,用X宏作为参数
将工作宏的名称传递给列表宏。这既避免了定义一个命名模糊的宏(
X
),又减轻了取消定义它的需要。
,在OP的用例中,导致以下三个文件:
// project_errno.h
#ifndef PROJECT_ERRNO_H
#define PROJECT_ERRNO_H
#define FOR_EACH_ERR_ID_VALUE_PAIR(DO)
DO(PROJECT_ERR_KEY_FAILURE, 12222)
DO(PROJECT_ERR_CIPHER_ZERO_PADDING, 12345)
DO(PROJECT_ERR_FAILED_TO_SETUP_ENC_KEY, 14004)
#define DEFINE_ENUM_ITEM(err, value) err = value,
enum project_errs {
FOR_EACH_ERR_ID_VALUE_PAIR( DEFINE_ENUM_ITEM )
};
#undef DEFINE_ENUM_ITEM
#endif
// logging.h
#ifndef LOGGING_H
#define LOGGING_H
const char* stringify_errno(int errno);
#endif
// logging.c
#include <stdio.h>
#include "project_errno.h"
#define STRINGIFY_ERR_VALUE_NAME(name, value) case name:
return "[" #value "] " #name;
const char* stringify_errno(int errno)
{
switch (errno) {
FOR_EACH_ERR_ID_VALUE_PAIR(STRINGIFY_ERR_VALUE_NAME)
default:
return "[-----] UNKWOWN";
}
}
#undef STRINGIFY_ERR_VALUE_NAME
可在此测试:https://wandbox.org/permlink/aNJCI7lQihkFnYzp
编辑回答:
我可以使用
生成枚举enum {
#define PROJECT_ERR_FUNC(name) , name =
PROJECT_ERR_START_OF_ENUM = -1
#include "project_errno.hx"
#undef PROJECT_ERR_FUNC
};
,但必须删除project_errno.hx
末尾的反勾号。只有当不包含时,上面的代码才能工作。project_errno.h
。
一个完整的最小工作程序应该是
enum {
#define PROJECT_ERR_FUNC(name) , name =
PROJECT_ERR_START_OF_ENUM = -1
#include "project_errno.hx"
#undef PROJECT_ERR_FUNC
};
#include <iostream>
int main() {
std::cout << PROJECT_ERR_KEY_FAILURE << std::endl;
return 0;
}
将打印12222
。