宏以避免重复的案例值

use*_*462 4 c macros

我在C中使用switch表达式来评估errno变量.根据手册页send():

EAGAIN或EWOULDBLOCK

The socket is marked nonblocking and the requested operation would block.
POSIX.1-2001 allows either error to be returned for this case,and does not
require these constants to have the same value, so a portable application
should check for both possibilities.
Run Code Online (Sandbox Code Playgroud)

由于我的申请必须是便携式的,我必须这样做:

switch (errno):
  case EWOULDBLOCK:
  case EAGAIN:
    //do whatever
    break;
  case EINTR:
    //...
Run Code Online (Sandbox Code Playgroud)

问题是,对于某些平台,EWOULDBLOCK和EAGAIN确实具有相同的值,因此在编译时我得到:

 connection.cxx:190:5: error: duplicate case value
 case EWOULDBLOCK:
 ^
 connection.cxx:189:5: error: previously used here
 case EAGAIN:
 ^
Run Code Online (Sandbox Code Playgroud)

所以我想我可以使用一个宏宏,取决于EWOULDBLOCK和EAGAIN是否具有相同的值,平台将该行添加到代码中或省略它.

有关如何编写该宏的任何想法?

Mik*_*ord 8

就像是:

 #if EAGAIN != EWOULDBLOCK
      case EAGAIN:
 #endif
      case EWOULDBLOCK:
Run Code Online (Sandbox Code Playgroud)

编辑:但是如果你要有很多switch switch语句,宏会比条件编译好.就像是:

 #if EAGAIN == EWOULDBLOCK
 #define MY_AGAIN EAGAIN
 #else
 #define MYAGAIN EAGAIN: case EWOULDBLOCK
 #endif
Run Code Online (Sandbox Code Playgroud)

然后使用它:

 case MY_AGAIN:
Run Code Online (Sandbox Code Playgroud)

您会看到冒号在调用它时不是宏的一部分:

 case ---->MACRO GOES HERE<-----:
Run Code Online (Sandbox Code Playgroud)

但是在第二种情况下,在原始周围文本的上下文中展开时:

 case EAGAIN: case EWOULDBLOCK:
Run Code Online (Sandbox Code Playgroud)

如果它是在你的switch语句中明确写出但是完全合法的C代码,那将是非常难看的.


nne*_*neo 5

不要用switch,然后; 只是用

if(errno == EWOULDBLOCK || errno == EAGAIN) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

编译器当然会愉快地将其优化为单个测试,如果EWOULDBLOCK事实上等于EAGAIN.

  • 虽然您的代码是正确的,但它比我提供的任何一个宏都慢,并且使用的空间更多.switch/case语句通常实现为跳转表,它非常紧凑和快速.这并不总是重要,但有时它确实如此. (2认同)
  • @MichaelCrawford:您正在检查系统调用背后的 errno,该调用通常需要数千到数十万个周期才能执行,并且您正在(最多)1-2 台机器上讨价还价错误检查结束的循环?并且您不相信编译器可以看到 `if` 测试只是透明地检查一个简单的值并对其进行优化? (2认同)