Очень сложно понять логику шестнадцатеричного кода ниже. Может ли кто-нибудь объяснить амперсанд в состоянии переключателя и как рассчитывается этот previousTagSize.

- (void)parse:(NSInputStream*)inputStream {

  NSInteger MASK = 0x1f;
  NSInteger Type1 = 8;
  NSInteger Type2 = 9;
  NSInteger Type3 = 18;

    uint8_t header[11];
    long len = [inputStream read:header maxLength:11];

    //How does it work?
    switch (header[0] & MASK) {
        case  Type1:
            self.type = Type_1;
            break;
        case Type2:
            self.type = Type_2;
            break;
    }

    self.dataSize = ((header[1] & 0x000000FF) << 16) | ((header[2] & 0x000000FF) << 8) | (header[3] & 0x000000FF);

        // read previous tag size
    uint8_t tagSize[4];
    [inputStream read:tagSize maxLength:4];
    int previousTagSize = ((tagSize[0] & 0x000000FF) << 24) |
                          ((tagSize[1] & 0x000000FF) << 16) |
                          ((tagSize[2] & 0x000000FF) << 8) |
                          (tagSize[3] & 0x000000FF);

    if (previousTagSize != 11 + self.dataSize) {
        NSLog(@"Invalid .");
    }
}
-1
user10355502 23 Сен 2018 в 09:39

1 ответ

Лучший ответ

Мне очень сложно понять логику нижеприведенного шестнадцатеричного кода.

«Логика» не шестнадцатеричная, это комбинация целочисленной и поразрядной логики.

«Шестнадцатеричный» - это всего лишь один из способов представления целочисленного значения в тексте программы Objective-C. То, что компьютер, на котором скомпилировал Objective-C, выполняет в виде упорядоченной последовательности бит , будет одним и тем же независимо от текстового представления целого числа в тексте вашей программы.

Например, 104 (десятичный), 0x68 (шестнадцатеричный) и 0150 (восьмеричный), если они хранятся в байтах, все представлены с использованием одной и той же упорядоченной последовательности битов 01101000. Компьютер также видит символ UTF-8 "h" как ту же упорядоченную последовательность битов.

(Примечание: в этом ответе я использую байты или 8 бит, чтобы не набирать много нулей, NSInteger на 64-битной машине составляет 64 бита, но для значений, используемых в приведенных здесь примерах, первое 56 из этих битов все равны нулю.)

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

Не могли бы вы объяснить амперсанд в состоянии переключателя

Оператор & в Objective-C является побитовым и , то есть упорядоченные последовательности битов в двух операндах объединяются попарно с использованием логического (также известного как Boolean) и функции ({{X1} }, 0 and 1 = 0, 1 and 0 = 0 и 1 and 1 = 1). Фрагмент кода:

header[0] & MASK

Использует & для выполнения операции маскирования - если вы посмотрите на функции и , если один операнд является 1, результатом будет другой операнд , если это 0, результатом будет 0, поэтому и можно использовать для «маскировки» части последовательности.

Например, представьте, что если header[0] содержит представление нашего 104 сверху, это представление в виде 8 бит будет 01101000. Представление MASK, имеющего значение 0x1F в виде 8 битов, равно 00011111. Объедините эти два представления, используя побитовое представление, и получите последовательность 00001000, где первые 3 нуля связаны с нулями во втором операнде ("маске"), а 5-битная последовательность 01000 такая же, как последние пять бит первого операнда, поскольку второй операнд состоит из единиц.

После этого поразрядно и если результирующая последовательность битов интерпретируется как целое число, значение будет 8, которое просто имеет то же значение, что и Type1 в программе.

Таким образом, эффект switch заключается в выборе на основе целочисленной интерпретации последних 5 битов header[0]. Этот тип кода, например, возникает, когда несколько значений данных были упакованы в более крупные единицы хранения - в данном случае 5 бит из 64 (размер памяти NSInteger на 64-битном компьютере).

и как рассчитывается предыдущий размер тега .

Опять же, это просто побитовые операции, оператор | побитовое или , а оператор << - сдвиг влево , одинарный битовый сдвиг влево отбрасывает крайний левый бит упорядоченной последовательности битов и добавляет бит 0 к крайнему правому концу (чтобы последовательность оставалась той же длины). Полный фрагмент:

int previousTagSize = ((tagSize[0] & 0x000000FF) << 24) |
                      ((tagSize[1] & 0x000000FF) << 16) |
                      ((tagSize[2] & 0x000000FF) << 8) |
                      (tagSize[3] & 0x000000FF);

Объединяет 4 значения, каждое из которых замаскировано до 8 бит [*], в одну 32-битную (размер int в Objective-C) последовательность.

HTH

[*] Маскирование требуется, если значение является типом со знаком, даже если значение соответствует целевому количеству битов для удаления лишних (в 4-битном представлении с дополнением до двух 0101 представляет 5 1101 представляет -3; в 8 битах это будут 00000101 и 11111101 соответственно, маскирование удаляет лишние единицы во втором случае, иначе они повлияют на правильность упаковки. Удаленные единицы восстанавливаются при распаковке.Подробнее читайте в дополнении 2.

1
Community 20 Июн 2020 в 09:12