возможные выводы кода с помощью fork () - PullRequest
0 голосов
/ 25 августа 2018

Учитывая следующий короткий код, я нахожу довольно трудным найти возможные напечатанные значения a и b:

main()
{
            int a,b;
 
    if ( ( a=fork() ) || ( b=fork() ) )
            printf ( "a=%d,b=%d\n" , a , b );

}

Я предполагаю, что мне не удается понять, какой из них обрабатывает отец или сынare.

Насколько я понимаю, печать будет выполняться, только если a = 0 или b = 0.Предположим, что a = 0, мы получаем 2 печатные строки (из-за использования fork) этого:

a=0, b=garbage value

Предположим, b = 0, мы получаем 2 печатные строки этого:

a=garbage value, b=0

Конечно, в случае неудачи fork не может быть никакого вывода.

Я уверен, что где-то ошибаюсь ... любая помощь будет оценена.

1 Ответ

0 голосов
/ 25 августа 2018

Насколько я понимаю, печать будет выполняться, только если a = 0 или b = 0

Это назад. Печать произойдет, когда одно из выражений по обе стороны от || будет ненулевым . Также кажется, что вы также можете не знать, что выражение в правой части || вычисляется только в том случае, если выражение в левой части равно нулю; это называется оценка короткого замыкания . (Аналогично, правая часть && оценивается только в том случае, если левая сторона отлична от нуля.)

При условии, что ни один вызов fork не завершится неудачей, существует только три ветви выполнения, потому что каждый процесс вызывает fork не более одного раза. printf вызывается дважды.

  • оригинальный процесс: a=fork() устанавливает a в ненулевое значение

    • левая сторона || не равна нулю, поэтому правая сторона не оценивается
    • printf вызывается с a ненулевым и b неинициализированным
  • дочерний процесс: a=fork() устанавливает a в ноль

    • левая сторона || равна нулю, поэтому правая сторона оценивается
    • b=fork() устанавливает b в ненулевое значение
    • правая сторона || отлична от нуля
    • printf вызывается с a нулем и b ненулевым
  • процесс внука: b=fork() устанавливает b на ноль

    • левая и правая части || равны нулю
    • printf не называется

Вывод дочернего и исходного процессов может отображаться в любом возможном порядке. Поскольку printf вызывается только после , каждый процесс выполняет вызовы fork, не нужно беспокоиться о дублированном буферизованном выводе.

Из-за "короткого замыкания" поведения || и порядка вычисления (x=fork()) вы никогда не сравниваете неинициализированное значение с нулем, но вы передаете неинициализированное значение printf в одной ветви выполнение. Это ошибка. Вы должны инициализировать оба a и b в ноль, когда они объявлены, для удобства чтения. Кроме того, их тип должен быть pid_t (и вы должны включить unistd.h, а также stdio.h).

Кстати, каждый раз, когда вы ставите пробелы внутри скобок или слева от запятой, Бог убивает котенка. Пожалуйста, подумайте о котятах.

Кстати, если у вас fork, вы работаете в Unix, которая не поддерживает объявление main с типом возврата void. Вы должны написать int main(void) вместо этого. Вы также должны завершить тело main с помощью return 0;, это технически необязательно в C99 и более поздних версиях, но существует огромное количество компиляторов, которые по умолчанию используют C89, и в любом случае я думаю, что полагаться на неявное возвращение 0 - плохой стиль. .

EDIT , поскольку я вижу, что вы решили эту проблему, изменив код для объявления main() без какого-либо возвращаемого типа: это технически объявляет, что он возвращает int, но полагается на устаревшую функцию называется "неявный int". В наши дни это считается вопиюще плохим стилем. Некоторые люди даже скажут вам, что «implicit int» был удален из языка, что верно, если вы идете по букве стандарта, но false, если вы придерживаетесь того, что на самом деле принимают компиляторы. Также неправильно ставить ничего в скобках аргумента; в C это не объявляет функцию, которая не принимает аргументов, она объявляет функцию, которая принимает неопределенное число аргументов. (Опять же, если перейти к букве стандарта, функция определение с пустыми круглыми скобками аргументов объявляет, что она не принимает аргументов, но это не тот случай, когда компиляторы фактически принимают.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...