[英]How to use switch statement inside a macro in C?
I want to use switch statement inside a macro in C. I have the following code segment: 我想在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.\n", __FILE__, __LINE__, MESSAGE(err)); \
exit(EXIT_FAILURE); \
But, this throws an error message, more specificially: 但是,这会抛出一条错误消息,更具体地说:
error: expected expression before 'switch' 错误:'switch'之前的预期表达式
Why is this happening exactly, and what is the proper way to use switch inside a macro in C? 为什么会发生这种情况,在C中使用宏内部切换的正确方法是什么?
you cannot return
from a macro and expect that it behaves like a function. 你不能从宏return
并期望它的行为像一个函数。 The macro code is expanded literally in your code, so now you have a switch/case & a bunch of return
statements in the last parameter of printf
! 宏代码在你的代码中逐字扩展,所以现在你在printf
的最后一个参数中有一个switch / case和一堆return
语句!
Besides, there's no advantage to use a macro here since you're not using token pasting, stringing or other macros like __FILE__
or __LINE__
in it (as opposed to your THROW_ERROR
macro which uses them). 此外,有没有优势,在这里使用宏,因为你不使用标记粘贴,粘连或其他类似的宏__FILE__
和__LINE__
在它(而不是你的THROW_ERROR
使用它们宏)。
Instead, define a MESSAGE
(or better: message
) function: 相反,定义一个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
}
and pass that to printf
并将其传递给printf
As an aside, wrap your THROW_ERROR
macro within braces since there are 2 statements: THROW_ERROR
,将THROW_ERROR
宏包装在大括号中,因为有两个语句:
#define THROW_ERROR(err) do { \
fprintf(stderr, "Error in %s:%d: %s.\n", __FILE__, __LINE__, message(err)); \
exit(EXIT_FAILURE); } while(0)
else if you do: 否则如果你这样做:
if (fail_code) THROW_ERROR(12);
then only the fprintf
statement is executed when an error occurs, and exit
happens no matter what! 然后在发生错误时只执行fprintf
语句,无论如何都exit
!
You misunderstand the macro in C. It is only the textual replacement. 你误解了C中的宏。它只是文本的替代品。
You need to use function for it: 你需要使用它的功能:
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 "";
}
you can od course create insane ternary macro: 你可以创建疯狂的三元宏:
#define MESSAGE(err) (err == ERROR_NO_MEMORY ? MSG_NO_MEMORY : err == ERROR_INVALID_INDEX ? MSG_INVALID_INDEX : .... )
With the expression statement extension (implemented on gcc, clang, and tinycc), you can do: 使用表达式语句扩展(在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; })
naturally, this isn't "portable" standard C. Portably you could use either an inline function (pretty much unchanged) or a macro with nested ternary expressions: 当然,这不是“可移植”标准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 )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.