Что (* (int *) & (w)) означает в c программировании? - PullRequest
0 голосов
/ 19 февраля 2020

Я изучаю процессы и в следующем фрагменте кода:

/* 
 * fork10 - Synchronizing with multiple children (wait)
 * Reaps children in arbitrary order
 * WIFEXITED and WEXITSTATUS to get info about terminated children
 */
void fork10()
{
    pid_t pid[N];
    int i, child_status;

    for (i = 0; i < N; i++)
    if ((pid[i] = fork()) == 0) {
        exit(100+i); /* Child */
    }
    for (i = 0; i < N; i++) { /* Parent */
        pid_t wpid = wait(&child_status);
        if (WIFEXITED(child_status))
            printf("Child %d terminated with exit status %d\n", wpid, WEXITSTATUS(child_status));
        else
            printf("Child %d terminate abnormally\n", wpid);
    }
}

когда я отслеживаю WIFEXITED определение функции, это то, что я получил:

#define WIFEXITED(x)    (_WSTATUS(x) == 0)
#define _WSTATUS(x) (_W_INT(x) & 0177)
#define _W_INT(w)   (*(int *)&(w))  /* convert union wait to int */

I есть два вопроса:

  1. Зачем использовать маску 0177 вместо 0b1111111, я видел это много раз, в чем преимущества использования восьмеричного числа по сравнению с другими форматами? Лично я нахожу двоичный код более интуитивным.
  2. В чем смысл (*(int *)&(w))?

Спасибо!

Ответы [ 5 ]

6 голосов
/ 19 февраля 2020

Двоичные константы, такие как 0b1111111, не определены стандартом C и были введены как расширение некоторыми реализациями C несколько позже, поэтому в более раннем коде обязательно использовались восьмеричные и шестнадцатеричные константы, и программисты привыкли к ним , Кроме того, восьмеричное число более компактно, и я могу посчитать количество установленных бит в 0177 легче, чем в 0b1111111. Человек быстро привыкнет к тому, что 7 означает три набора битов.

В (*(int *)&(w)), &(w) принимает адрес объекта, обозначенный w. Затем (int *) преобразует этот адрес из типа «указатель на тип w» в «указатель на int». Затем * разыменовывает этот указатель, номинально создавая значение int.

Цель состоит в том, чтобы получить доступ к первым байтам w, как если бы они были int, эффективно получая необработанные биты, которые являются в w вместо того, чтобы интерпретировать его как структуру или любой другой тип. Это называется псевдоним .

Псевдоним таким образом не поддерживается стандартом C, но многие реализации C позволяют это делать, и показанный вами код кажется написанным специально для такой реализации.

Поддерживаемый способ получения необработанных битов объекта - это индивидуальное копирование байтов, например:

int b;
memcpy(&b, &w, sizeof b);

Хотя это выглядит как вызов функции, хорошо компиляторы распознают его как запрос доступа к первым байтам w, как если бы они были int, и оптимизируют его. Результатом может быть одна инструкция загрузки. Однако, оборачивая это в макрос, который выдает int как значение, возникают некоторые сложности, которые я оставлю для дальнейшего обсуждения в другом месте. (Вы можете задать новый вопрос об этом, если хотите.)

2 голосов
/ 19 февраля 2020

1 Зачем использовать маску 0177 вместо 0b1111111 ...?

(Этот ответ касается только этой части вашего вопроса)

Поскольку 0b1111111 не C целочисленная константа на 6.4.4.1. Целочисленные константы :

Синтаксис

1

      integer-constant:
            decimal-constant integer-suffixopt
            octal-constant integer-suffixopt
            hexadecimal-constant integer-suffixopt
      decimal-constant:
            nonzero-digit
            decimal-constant digit
      octal-constant:
            0
            octal-constant octal-digit
      hexadecimal-constant:
            hexadecimal-prefix hexadecimal-digit
            hexadecimal-constant hexadecimal-digit
      hexadecimal-prefix: one of
            0x   0X
      nonzero-digit: one of
            1   2   3   4   5   6   7   8   9
      octal-digit: one of
            0   1   2   3   4   5   6   7
      hexadecimal-digit: one of
            0   1   2   3   4   5   6   7   8   9
            a   b   c   d   e   f
            A   B   C   D   E   F
      integer-suffix:
            unsigned-suffix long-suffixopt
            unsigned-suffix long-long-suffix
            long-suffix unsigned-suffixopt
            long-long-suffix unsigned-suffixopt
      unsigned-suffix: one of
            u   U
      long-suffix: one of
            l   L
      long-long-suffix: one of
            ll   LL

Описание

2 Целочисленная константа начинается с di git, но не имеет периода или части экспоненты. Он может иметь префикс, который определяет его базу, и суффикс, который определяет его тип.

3 Десятичная константа начинается с ненулевого ди git и состоит из последовательности десятичных цифр. Восьмеричная константа состоит из префикса 0, за которым может следовать только последовательность цифр от 0 до 7. Шестнадцатеричная константа состоит из префикса 0x или 0X, за которым следует последовательность десятичных цифр и букв от a (или A) до f (или F) со значениями от 10 до 15 соответственно.

По стандарту , C поддерживает только десятичные, восьмеричные и шестнадцатеричные целочисленные константы.

1 голос
/ 19 февраля 2020

О вашем первом вопросе: двоичные литералы официально не являются частью стандарта C (и являются только частью C ++ начиная с C ++ 14), поэтому использование восьмеричных литералов вместо их использования может улучшить переносимость.

О вашем втором вопросе: &w принимает адрес w, который затем преобразуется в указатель на int ((int*)&w), на который делается разыменование. Что это эффективно делает, так это чтение памяти из w, как если бы w было int.

1 голос
/ 19 февраля 2020
    1. Преимущество состоит в том, что не требуется никаких дополнительных символов в виде цифр (шестнадцатеричная система - это основание-16, поэтому для нее требуется шесть дополнительных символов, кроме 0–9). Он также используется для цифровых дисплеев.
  1. Вы пытаетесь преобразовать его в целочисленный указатель и сослаться на значение из него.
0 голосов
/ 24 февраля 2020

Вы должны проверить эту ссылку, это поможет вам решить любой вопрос, используя (Правило по часовой стрелке / спираль)

http://c-faq.com/decl/spiral.anderson.html?fbclid=IwAR3V_KR4VwO33UvbO4LgN3AIW_79QBWAR9qHO2KHyyJgEuIKiFQOQTCec5U

( ( int ) & (w)) сначала & w означает адрес w, где & является оператором адреса, затем (int *) означает создание указателя на целое число, поэтому (до этого шага у вас есть указатель, который указывает на адрес w) указатель означает (вы получили доступ к значению w)

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