Любое преимущество в использовании макроса 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?

4 ответов


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

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

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


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

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

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

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

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


насколько я могу судить по проверке одной спецификации Unix,код система хранит статус выхода во втором-самом правом октете, но я не верю стандартный делает. Таким образом, вы должны использовать макросы по крайней мере по нескольким причинам:

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

здесь 0xff00-двоичная маска (текст ссылки). ANDing it with a value устанавливает все биты в ноль, за исключением второго байта (считая справа).

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

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

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