鉴于下面的短代码,我发现要找出a和b的可能打印值非常困难:
main()
{
int a,b;
if ( ( a=fork() ) || ( b=fork() ) )
printf ( "a=%d,b=%d\n" , a , b );
}
我想我无法理解父进程或子进程是哪一个。
据我了解,仅当a = 0或b = 0时才进行打印。假设a = 0,我们得到2条印刷线(由于使用fork):
a=0, b=garbage value
假设b = 0,我们得到2条印刷行:
a=garbage value, b=0
当然,如果fork无法成功,就不会有输出。
我确信在某个地方我错了。任何帮助都会得到补偿。
答案 0 :(得分:2)
据我了解,仅当a = 0或b = 0时才进行打印
这是向后的。当||
两侧的任一表达式为 nonzero 时,将进行打印。似乎您也可能不知道||
右侧的表达式仅在左侧的表达式为零时才求值;这称为短路评估。 (同样,&&
的右侧仅在左侧非零时才被评估。)
假设对fork
的调用没有失败,则只有三个执行分支,因为每个进程最多只能调用fork
。 printf
被两次呼叫。
原始过程:a=fork()
将a
设置为非零值
||
的左侧非零,因此右侧不进行评估printf
用a
非零和b
未初始化的方式调用子进程:a=fork()
将a
设置为零
||
的左侧为零,因此求出右侧b=fork()
将b
设置为非零值||
的右侧不为零printf
用a
零和b
非零来调用孙子进程:b=fork()
将b
设置为零
||
的左侧和右侧均为零子进程和原始进程的输出可能以两种可能的顺序出现。由于printf
仅在之后被调用,因此每个过程都对fork
进行了调用,因此不必担心重复的缓冲输出。
由于||
的“短路”行为和(x=fork())
的求值顺序,您永远不会将未初始化的值与零进行比较,而是将未初始化的值传递给{{1 }}在执行的一个分支上。这是一个错误。为了便于阅读,在声明printf
和a
时都应将它们初始化为零。此外,其类型应为b
(并且您应同时包含pid_t
和unistd.h
)。
顺便说一句,每当您在括号内或逗号的左侧放置空格时,上帝就会杀死一只小猫。请想想小猫。
顺便说一句,如果您拥有stdio.h
,则使用的是Unix,它不支持使用返回类型fork
声明main
。您应该改写void
。您还应该使用int main(void)
结束main主体,这在C99及更高版本中从技术上讲是没有必要的,但是仍然有很多编译器默认使用C89,无论如何,我认为依靠隐式return 0是风格不好。
编辑,因为我看到您通过更改代码以声明return 0;
根本没有返回类型来解决此问题:从技术上讲确实声明它返回main()
,但是依赖于过时的功能,称为“隐式int”。如今,这被认为是“非常糟糕”的风格。甚至有人会告诉您,该语言已删除了“隐式int”,如果您遵循标准的字母,则为true;如果遵循编译器实际接受的内容,则为false。在参数括号之间不加任何内容也是错误的。在C语言中,它没有声明不带参数的函数,而是声明了带未指定数量个参数的函数。 (同样,如果按照标准的字母,带有空参数括号的函数 definition 会声明它不带参数,但是编译器实际接受的情况并非如此。)>