Предположим, у меня есть 'numb'=1025 [00000000 00000000 00000100 00000001]
представленное число :
На Little-Endian Machine:
00000001 00000100 00000000 00000000
На Big-Endian Machine:
00000000 00000000 00000100 00000001
Теперь, если я применю сдвиг влево на 10 битов (то есть: numb << = 10), я должен иметь:
[A] На Little-Endian Machine:
Как я заметил в GDB, Little Endian выполняет сдвиг влево в 3 этапа: [Я показал «3» шага, чтобы лучше понять только обработку]
Лечи нет. в Big-Endian Convention:
00000000 00000000 00000100 00000001
Применить сдвиг влево:
00000000 00010000 00000100 00000000
Представьте Результат снова в Little-Endian:
00000000 00000100 00010000 00000000
[B]. На Big-Endian Machine:
00000000 00010000 00000100 00000000
Мой вопрос:
Если я непосредственно применяю сдвиг влево к конвенции Little Endian, это должно дать:
numb
:
00000001 00000100 00000000 00000000
numb << 10
:
00010000 00000000 00000000 00000000
Но на самом деле это дает:
00000000 00000100 00010000 00000000
Чтобы достичь только второго результата, я показал три гипотетических шага выше.
Пожалуйста, объясните мне, почему вышеупомянутые два результата отличаются: Фактический результат numb << 10
отличается от ожидаемого результата.
источник
Нет, битовое смещение, как и любая другая часть C, определяется в терминах значений , а не представлений. Сдвиг влево на 1 - это умножение на 2, сдвиг вправо - это деление. (Как всегда при использовании побитовых операций, остерегайтесь подписи. Все наиболее четко определено для целых типов без знака.)
источник
x &= -1u << 20
, наиболее вероятно, будет неправильным, еслиx
он 64-битный иint
32-битный. По этой причине GCC обещает никогда не рассматривать подписанные смены как неопределенные или даже неуказанные.Независимо от того, какая команда сдвига сдвигает биты старшего разряда в первую очередь, считается левым сдвигом. Какая бы команда сдвига ни сдвинула младшие биты первыми, считается правильным сдвигом. В этом смысле поведение
>>
и<<
дляunsigned
чисел не будет зависеть от порядка байтов.источник
Компьютеры не записывают цифры так, как мы. Значение просто меняется. Если вы настаиваете на том, чтобы смотреть на него побайтово (хотя компьютер этого не делает), вы могли бы сказать, что на машине с прямым порядком байтов первый байт сдвигается влево, избыточные биты переходят во второй байт, и так далее.
(Кстати, little-endian имеет больше смысла, если вы пишете байты по вертикали, а не по горизонтали, с более высокими адресами сверху. Именно так обычно и выглядят диаграммы карты памяти.)
источник
Хотя принятый ответ указывает на то, что бесконечность является понятием с точки зрения памяти. Но я не думаю, что это ответит на вопрос напрямую.
Некоторые ответы говорят мне, что побитовые операции не зависят от порядка байтов , и процессор может представлять байты любым другим способом. Во всяком случае, речь идет об этой абстракции.
Но когда мы делаем некоторые побитовые вычисления, например, на бумаге, не нужно ли указывать порядковый номер в первую очередь? В большинстве случаев мы выбираем порядок байтов неявно.
Например, предположим, что у нас есть строка кода, подобная этой
0x1F & 0xEF
Как бы вы рассчитали результат вручную, на бумаге?
Поэтому здесь мы используем формат Big Endian, чтобы сделать расчет. Вы также можете использовать Little Endian для расчета и получения того же результата.
Кстати, когда мы пишем числа в коде, я думаю, что это формат Big Endian.
123456
или0x1F
наиболее значимые цифры начинаются слева.Опять же, как только мы напишем какой-нибудь двоичный формат значения на бумаге, я думаю, что мы уже выбрали Endianess, и мы рассматриваем значение так, как мы видим его из памяти.
Итак, возвращаясь к вопросу, операция сдвига
<<
должна рассматриваться как смещение от младшего бита (младший байт) к старшему биту (старший байт) .Тогда как для примера в вопросе:
numb=1025
Little Endian
LSB 00000001 00000100 00000000 00000000 MSB
Так
<< 10
будет10bit
переход от LSB к MSB.Сравнение и
<< 10
операции для формата Little Endian шаг за шагом:Вот Это Да! Я получаю ожидаемый результат, как описано в ОП!
Проблемы, которые ОП не получил ожидаемый результат, заключаются в том, что:
Кажется, он не перешел от LSB к MSB.
При перемещении битов в формате Little Endian вы должны понимать (слава богу, я это понимаю), что:
LSB 10000000 00000000 MSB << 1
этоLSB 00000000 00000001 MSB
, неLSB 01000000 00000000 MSB
Потому что для каждого человека
8bits
мы пишем его в форматеMSB 00000000 LSB
Big Endian.Так это как
LSB[ (MSB 10000000 LSB) (MSB 00000000 LSB) ]MSB
Подводить итоги:
Хотя побитовые операции называются абстрагированными, блаблабла ..., когда мы вычисляем побитовые операции вручную, нам все равно нужно знать, какую последовательность мы используем, записывая двоичный формат на бумаге. Также нам нужно убедиться, что все операторы используют один и тот же порядок байтов.
ОП не получил ожидаемый результат, потому что он сделал сдвиг неправильно.
источник