mzo*_*zoz 0 c operating-system process
我正在学习流程和以下代码片段:
/*
* fork10 - Synchronizing with multiple children (wait)
* Reaps children in arbitrary order
* WIFEXITED and WEXITSTATUS to get info about terminated children
*/
void fork10()
{
pid_t pid[N];
int i, child_status;
for (i = 0; i < N; i++)
if ((pid[i] = fork()) == 0) {
exit(100+i); /* Child */
}
for (i = 0; i < N; i++) { /* Parent */
pid_t wpid = wait(&child_status);
if (WIFEXITED(child_status))
printf("Child %d terminated with exit status %d\n", wpid, WEXITSTATUS(child_status));
else
printf("Child %d terminate abnormally\n", wpid);
}
}
Run Code Online (Sandbox Code Playgroud)
当我跟踪WIFEXITED函数定义时,这就是我所得到的:
#define WIFEXITED(x) (_WSTATUS(x) == 0)
#define _WSTATUS(x) (_W_INT(x) & 0177)
#define _W_INT(w) (*(int *)&(w)) /* convert union wait to int */
Run Code Online (Sandbox Code Playgroud)
我有两个问题:
0177而不是0b1111111,我已经见过很多次了,使用八进制数比其他格式有什么好处?我个人觉得二进制更直观。(*(int *)&(w))?谢谢!
诸如0b1111111C 标准未定义的二进制常量,有些 C 实现作为扩展引入,有些晚了,因此早期的代码必然使用八进制和十六进制常量,程序员已经习惯了它们。此外,八进制更紧凑,我可以0177比0b1111111. 人们很快就会习惯于知道这7意味着设置了三个位。
在 中(*(int *)&(w)),&(w)获取由 指定的对象的地址w。然后(int *)将该地址从“指向 w 类型的指针”类型转换为“指向 int 类型的指针”。然后*取消引用该指针,名义上产生一个int值。
目的是访问 的第一个字节,w就好像它们是 an 一样int,有效地获取其中的原始位,w而不是将其解释为结构或任何其他类型。这称为混叠。
C 标准不支持这种方式的别名,但许多 C 实现允许它,并且您显示的代码似乎是专门为这种实现编写的。
获取对象原始位的一种受支持的方法是单独复制字节,如下所示:
int b;
memcpy(&b, &w, sizeof b);
Run Code Online (Sandbox Code Playgroud)
尽管这看起来像一个函数调用,但优秀的编译器会将其识别为访问was的第一个字节int并对其进行优化的请求。结果可能是单个加载指令。然而,将它包装到一个产生int作为值的宏中会涉及一些复杂性,我将在别处进一步讨论。(如果需要,您可以就此提出一个新问题。)