Подтвердить что ты не робот

Любая польза от использования макроса WEXITSTATUS в C над делением на 256 при статусе exit()?

Я делал упражнение для университета, где мне приходилось возвращать значение с выходом, это значение на самом деле было чем-то подсчитанным. Это может быть выше 255 (к которому не удается обработать exit()), но учитель предложил использовать тестовые данные, где счетчик никогда не мог превышать это значение.

После всего этого мне нужно было обработать это значение счета, статус выхода, я получил это значение в основном процессе, используя waitpid(). К моему удивлению, если дочерний процесс вернулся 1, "реальным" значением в основном процессе было 256, 2 - 512 и так далее...

Мне нужно было напечатать это значение, поэтому я просто разделил его на 256, и это было сделано. Однако, если я использую макрос WEXITSTATUS(), я также получу это значение так, как хочу...

Я посмотрел исходный код C, и вот что я узнал:

#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)

Я понимаю, что происходит здесь, например, 512 в двоичном формате - 10 0000 0000, смещение 8 o справа даст 00 0000 0010, что равно 2 десятичным. То, что я не понимаю в этом макросе, - это то, что оператор и тот факт, что 0xff00 кажется случайным числом (это, вероятно, нет, откуда оно взялось?). Что это делает в точности, почему в макросе есть "& 0xff00"? Не будет ли это работать?

И реальный вопрос в этом вопросе - это то же самое, что и этот макрос в моем коде, делящийся на 256?

4b9b3361

Ответ 1

И настоящий вопрос в этой теме, это то же самое, что и этот макрос в моем коде как деление на 256?

Он, вероятно, всегда будет работать в случаях, когда дочерний процесс обычно заканчивается (то есть, вызывая exit(), а не по ошибке сегментации, отказу утверждения и т.д.).

Состояние, сохраненное в waitpid(), кодирует как причину, по которой завершился дочерний процесс, так и код выхода. Причина хранится в младшем байте (полученном status & 0xff), а код выхода хранится в следующем байте (замаскирован status & 0xff00 и извлечен WEXITSTATUS()). Когда процесс заканчивается нормально, причина равна 0, и поэтому WEXITSTATUS просто эквивалентно сдвигу на 8 (или делению на 256). Однако, если процесс убит сигналом (например, SIGSEGV), кода выхода нет, и вы должны использовать WTERMSIG для извлечения номера сигнала из байт причины.

Ответ 2

Если переменная статуса представляет собой подписанное 16-разрядное целое число ( "короткое" ) на машине, где "int" - 32-разрядная величина, а если статус выхода находится в диапазоне 128..255, то WEXITSTATUS() все еще дает вам правильное значение, когда деление на 256 или просто смещение вправо даст вам неправильное значение.

Это связано с тем, что короткий символ будет расширен до 32 бит, а маскировка отменяет расширение знака, оставляя в результате правильное (положительное) значение.

Если машина использовала 16-битные целые числа, тогда код в WEXITSTATUS(), вероятно, сделает shift then mask, чтобы обеспечить аналогичное поведение:

#define WEXITSTATUS(status) (((status)>>8) & 0xFF)

Это потому, что реализация заботится о таких деталях для вас, что вы должны использовать макрос WEXITSTATUS().

Ответ 3

Насколько я могу судить по проверке Single Unix Spec, ваша система, как правило, сохраняет статус выхода во втором-крайнем октете, но я не верю стандарт. Итак, вы должны использовать макросы по крайней мере по нескольким причинам:

  • Они верны. Бит-сдвиг отрицательного числа делает разные вещи на разных платформах. Работает ли он так, как вы хотите? Я не знаю.
  • Они просты. Сразу видно, что делает WEXITSTATUS. Меньше с другими подходами. Если вы видели ручную версию WIFSIGNALED, вы бы узнали ее? Сколько потребуется времени, чем WIFSIGNALED.
  • Они переносимы. С тех пор, как спецификация говорит об этом, он будет работать на каждой системе (по крайней мере, почти в любой Unix-подобной системе).

Ответ 4

Здесь 0xff00 - это двоичная маска (текст ссылки). Инициализируя его значением, он устанавливает все биты в ноль, кроме второго байта (считая справа).

Вы должны использовать WEXITSTATUS только для процесса, который, как известно, вышел из него нормально. Эта информация предоставляется макросом WIFEXITED.

И реальный вопрос в этом вопросе - это то же самое, что и этот макрос в моем коде, делящийся на 256?

Макрос делает код более читаемым, и он гарантирует работу с любой совместимой с Posix реализацией. Насколько я знаю, Posix не определяет формат статуса, поэтому вы не можете ожидать, что ваш код будет работать везде.