fork()可能的代码输出

时间:2018-08-25 17:21:16

标签: c fork

鉴于下面的短代码,我发现要找出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无法成功,就不会有输出。

我确信在某个地方我错了。任何帮助都会得到补偿。

1 个答案:

答案 0 :(得分:2)

  

据我了解,仅当a = 0或b = 0时才进行打印

这是向后的。当||两侧的任一表达式为 nonzero 时,将进行打印。似乎您也可能不知道||右侧的表达式仅在左侧的表达式为零时才求值;这称为短路评估。 (同样,&&的右侧仅在左侧非零时才被评估。)

假设对fork的调用没有失败,则只有三个执行分支,因为每个进程最多只能调用forkprintf被两次呼叫。

  • 原始过程:a=fork()a设置为非零值

    • ||的左侧非零,因此右侧不进行评估
    • printfa非零和b未初始化的方式调用
  • 子进程:a=fork()a设置为零

    • ||的左侧为零,因此求出右侧
    • b=fork()b设置为非零值
    • ||的右侧不为零
    • printfa零和b非零来调用
  • 孙子进程:b=fork()b设置为零

    • ||的左侧和右侧均为零
    • 未调用printf

子进程和原始进程的输出可能以两种可能的顺序出现。由于printf仅在之后被调用,因此每个过程都对fork进行了调用,因此不必担心重复的缓冲输出。

由于||的“短路”行为和(x=fork())的求值顺序,您永远不会将未初始化的值与零进行比较,而是将未初始化的值传递给{{1 }}在执行的一个分支上。这是一个错误。为了便于阅读,在声明printfa时都应将它们初始化为零。此外,其类型应为b(并且您应同时包含pid_tunistd.h)。

顺便说一句,每当您在括号内或逗号的左侧放置空格时,上帝就会杀死一只小猫。请想想小猫。

顺便说一句,如果您拥有stdio.h,则使用的是Unix,它不支持使用返回类型fork声明main。您应该改写void。您还应该使用int main(void)结束main主体,这在C99及更高版本中从技术上讲是没有必要的,但是仍然有很多编译器默认使用C89,无论如何,我认为依靠隐式return 0是风格不好。

编辑,因为我看到您通过更改代码以声明return 0;根本没有返回类型来解决此问题:从技术上讲确实声明它返回main(),但是依赖于过时的功能,称为“隐式int”。如今,这被认为是“非常糟糕”的风格。甚至有人会告诉您,该语言已删除了“隐式int”,如果您遵循标准的字母,则为true;如果遵循编译器实际接受的内容,则为false。在参数括号之间不加任何内容也是错误的。在C语言中,它没有声明不带参数的函数,而是声明了带未指定数量个参数的函数。 (同样,如果按照标准的字母,带有空参数括号的函数 definition 会声明它不带参数,但是编译器实际接受的情况并非如此。)