在退出()状态下使用C中的WEXITSTATUS宏超过256的任何好处?

我正在为大学做一个练习,我必须用退出返回一个值,这个值实际上是一些东西。 这可能高于255(exit()无法处理)但是老师建议使用测试数据,其中计数永远不会高于该值。

毕竟,我需要处理这个计数值,退出状态,我通过使用waitpid()在主进程中得到了这个值。 令我惊讶的是,如果子进程返回1,则主进程中的“实际”值为256,2为512,依此类推……

我需要打印这个值,所以我简单地将它除以256并完成了。 但是,如果我使用WEXITSTATUS()宏,我也会按照我想要的方式得到这个值…

我查看了C源代码,这是我发现的:

#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8) 

我理解这里发生了什么,例如,512 in binary是10 0000 0000,右移8 o将给00 0000 0010,即十进制2。 我在这个宏中不明白的是&运算符和0xff00似乎是一个随机数的事实(它可能不是,它来自哪里?)。 这究竟是做什么的,为什么宏中有“&0xff00”? 它不会有效吗?

在这个主题中真正的问题是,在我的代码中将此宏称为除以256是一回事吗?

在这个主题中真正的问题是,在我的代码中将此宏称为除以256是一回事吗?

它可能总是在子进程正常终止的情况下工作(即,通过调用exit(),而不是通过分段错误,断言失败等)。

waitpid()存储的状态编码子进程终止的原因和退出代码。 原因存储在最低有效字节(由status & 0xff获得)中,退出代码存储在下一个字节中(由status & 0xff00屏蔽并由WEXITSTATUS()提取)。 当进程正常终止时,原因是0,因此WEXITSTATUS只相当于移位8(或除以256)。 但是,如果进程被信号(例如SIGSEGV)杀死,则没有退出代码,您必须使用WTERMSIG从原因字节中提取信号编号。

如果状态变量是机器上有符号的16位整数(’短’),其中’int’是32位数量,如果退出状态在128..255范围内,那么WEXITSTATUS()仍然是给你一个正确的值,除以256或简单地向右移动将给你一个不正确的值。

这是因为short将符号扩展为32位,并且屏蔽撤消符号扩展,在结果中保留正确的(正)值。

如果机器使用16位整数,那么WEXITSTATUS()中的代码可能会移位然后掩码以确保类似的行为:

 #define WEXITSTATUS(status) (((status)>>8) & 0xFF) 

这是因为实现会为您处理这些细节,您应该使用WEXITSTATUS()宏。

从检查Single Unix Spec可以看出, 您的系统恰好将退出状态存储在第二个到最右边的八位字节中,但我不相信标准会这样做。 因此,您应该使用宏至少有几个原因:

  • 他们是对的。 对负数进行位移会在不同平台上执行不同的操作。 它是否按照你想要的方式工作? 我不知道。
  • 他们很简单。 它立即清楚WEXITSTATUS作用。 其他方法则较少。 如果你看到WIFSIGNALED版,你会认出来吗? 比WIFSIGNALED需要多WIFSIGNALED
  • 它们是便携式的。 由于它的规范如何实现,它将适用于每个系统(至少几乎每个类Unix系统)。

这里0xff00是二进制掩码( 链接文本 )。 使用值对其进行AND运算将所有位设置为零,但第二个字节除外(从右侧开始计数)。

您应该只对已知正常退出的进程使用WEXITSTATUS 。 此信息由WIFEXITED宏提供。

在这个主题中真正的问题是,在我的代码中将此宏称为除以256是一回事吗?

宏使代码更具可读性,并且可以保证在任何符合Posix的实现上工作。 据我所知,Posix没有指定状态的格式,因此您不能指望您的代码可以在任何地方使用。