与在 exit() 状态上除以 256 相比,在 C 中使用 WEXITSTATUS 宏有什么好处?

StackOverflow https://stackoverflow.com/questions/808541

  •  03-07-2019
  •  | 
  •  

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

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

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

我查看了 C 源代码,发现如下:

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

我明白这里发生了什么,例如,二进制的 512 是 10 0000 0000,向右移动 8 会得到 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.
  • 它们是便携式的。由于按照规范的要求,它可以在每个系统上运行(至少几乎每个类 Unix 系统)。

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

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

  

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top