Обычно, когда мне нужно выполнить форк в C, я делаю что-то вроде этого:
pid_t p = fork();
if (p == 0) { /* do child stuff */ }
else { /* do parent stuff and pray there wasn't an error */ }
Мне пришло в голову, что я могу отказаться от дополнительной переменной и использовать:
if (fork() == 0) { /* child */ }
else { /* parent/pray */ }
Помимо неправильной обработки ошибок, (почему) это работает / не работает?





Вы теряете идентификатор дочернего процесса в родительском процессе, который возвращается родительскому процессу. Я думаю, вы могли бы восстановить эту информацию, но, возможно, не однозначно (то есть, я думаю, вы могли бы получить PID всех своих детей, но не обязательно PID ребенка, которого вы только что разветвили). Если вам не нужно знать PID ребенка, я думаю, что второй способ подойдет.
Кроме того, -1 возвращается, если возникает ошибка при разветвлении, которую вы не проверяете ни в том, ни в другом случае, что обычно является ошибкой.
Вам следует сделать это вместо этого. Я никогда не знал, что это не сработает. Так это делается в книгах Стивенса.
int p;
if ((p = fork()) == 0) { /* child */ }
else { /* parent/pray */ }
Вы можете сделать это в C, и это будет работать, потому что родительский и дочерний будут получать разные возвращаемые значения от вилки - и это сначала оценивается. Как вы упомянули, единственные проблемы - это обработка ошибок. Кроме того, у вас не будет другого способа восстановить дочерний PID, если вы захотите с ним работать, например, с помощью waitpid и т. д.
То, что вы предлагаете, безусловно, сработает. Однако обработка ошибок не является обязательной в любом хорошо работающем приложении. Следующий шаблон реализации также лаконичен и обрабатывает ошибки. Кроме того, он сохраняет возвращаемое значение fork () в переменной pid на случай, если вы захотите использовать его позже в родительском элементе, например, для ожидания дочернего элемента.
switch (pid = fork()) {
case -1: /* Failure */
/* ... */
case 0: /* Child */
/* ... */
default: /* Parent */
/* ... */
}