如何在C中使用宏内的switch语句?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在C中使用宏内的switch语句?相关的知识,希望对你有一定的参考价值。
我想在C中的宏内部使用switch语句。我有以下代码段:
enum errors {
ERROR_NO_MEMORY,
ERROR_INVALID_INDEX,
ERROR_INVALID_VALUE
};
#define MSG_NO_MEMORY "could not allocate memory"
#define MSG_INVALID_INDEX "index out of bounds"
#define MSG_INVALID_VALUE "invalid value passed as input"
#define MESSAGE(err)
switch (err) {
case ERROR_NO_MEMORY:
return MSG_NO_MEMORY;
case ERROR_INVALID_INDEX:
return MSG_INVALID_INDEX;
case ERROR_INVALID_VALUE:
return MSG_INVALID_VALUE;
}
#define THROW_ERROR(err)
fprintf(stderr, "Error in %s:%d: %s.
", __FILE__, __LINE__, MESSAGE(err));
exit(EXIT_FAILURE);
但是,这会抛出一条错误消息,更具体地说:
错误:'switch'之前的预期表达式
为什么会发生这种情况,在C中使用宏内部切换的正确方法是什么?
答案
你不能从宏中return
并期望它的行为像一个函数。宏代码在你的代码中逐字扩展,所以现在你在return
的最后一个参数中有一个switch / case和一堆printf
语句!
此外,在这里使用宏没有任何好处,因为你没有使用标记粘贴,穿线或其他宏,如__FILE__
或__LINE__
(与使用它们的THROW_ERROR
宏相对)。
相反,定义一个MESSAGE
(或更好:message
)函数:
const char *message(int code)
{
switch (err) {
case ERROR_NO_MEMORY:
return MSG_NO_MEMORY;
case ERROR_INVALID_INDEX:
return MSG_INVALID_INDEX;
case ERROR_INVALID_VALUE:
return MSG_INVALID_VALUE;
}
return "unknown error"; // just in case no code matches
}
并将其传递给printf
顺便说一下,将THROW_ERROR
宏包装在括号内,因为有两个语句:
#define THROW_ERROR(err) do {
fprintf(stderr, "Error in %s:%d: %s.
", __FILE__, __LINE__, message(err));
exit(EXIT_FAILURE); } while(0)
否则如果你这样做:
if (fail_code) THROW_ERROR(12);
然后只有在发生错误时执行fprintf
语句,无论如何都会发生exit
!
另一答案
你误解了C中的宏。它只是文本的替代品。
你需要使用它的功能:
inline const char *MESSAGE(int code)
{
switch (err)
{
case ERROR_NO_MEMORY:
return MSG_NO_MEMORY;
case ERROR_INVALID_INDEX:
return MSG_INVALID_INDEX;
case ERROR_INVALID_VALUE:
return MSG_INVALID_VALUE;
}
return "";
}
你可以创建疯狂的三元宏:
#define MESSAGE(err) (err == ERROR_NO_MEMORY ? MSG_NO_MEMORY : err == ERROR_INVALID_INDEX ? MSG_INVALID_INDEX : .... )
另一答案
使用表达式语句扩展(在gcc,clang和tinycc上实现),您可以:
#define MESSAGE(err)
({ int MESSAGE; switch(err){
case ERROR_NO_MEMORY:
MESSAGE = MSG_NO_MEMORY;
case ERROR_INVALID_INDEX:
MESSAGE = MSG_INVALID_INDEX;
case ERROR_INVALID_VALUE:
MESSAGE = MSG_INVALID_VALUE;
}; MESSAGE; })
当然,这不是“可移植”标准C.可以使用内联函数(几乎没有变化)或使用嵌套三元表达式的宏:
#define MESSAGE(err)
( err==ERROR_NO_MEMORY ? MSG_NO_MEMORY
: err==ERROR_INVALID_INDEX ? MSG_INVALID_INDEX
: err==ERROR_INVALID_VALUE ? MSG_INVALID_VALUE
: 0 )
以上是关于如何在C中使用宏内的switch语句?的主要内容,如果未能解决你的问题,请参考以下文章