#c# #operators #bit-shift
#c# #операторы #битовый сдвиг
Вопрос:
Мне интересно, почему операторы сдвига (<< и >> ), эквивалентные умножению и делению соответственно, имеют меньший приоритет, чем аддитивный оператор, такой как » «.
Другими словами:
int a = 1 2 * 8; //yields 17
тогда как:
int a = 1 2 << 3; //yields 24
Кто-нибудь знает, в чем причина такого поведения?
ПРИМЕЧАНИЕ: Пожалуйста, не отвечайте мне «потому что так сказано в спецификациях»!
Заранее всем спасибо.
РЕДАКТИРОВАТЬ: я понял, что сдвиг влево может быть получен путем суммирования левого операнда сам по себе. Может быть, это причина?
Комментарии:
1. Сдвиг битов не является умножением. При определенных обстоятельствах его можно использовать для получения того же эффекта, что и умножение на степень два, но цели совершенно разные. Вы не можете умножить на 47, например, без какого-либо многословного алгоритма сдвига и накопления.
2. Полностью уважаю вашу точку зрения, но побитовое смещение математически ЯВЛЯЕТСЯ умножением, хотя вы не можете указать любые факторы, которые вы хотите. Лучше: здесь тоже задействована мощность, поэтому приоритет должен быть еще выше.
3. Цель сдвига битов — сдвигать биты, а не умножать. Я могу умножить число на три, просто добавив его к самому себе дважды (
a = a a a
), но это не преобразует намерениеоператора в умножение. Это также не приводит к волшебному сдвигу
таблицы приоритетов 🙂
Ответ №1:
Относительный приоритет арифметических операторов и побитовых операторов не имеет значения, потому что вы никогда не должны использовать их вместе в любом случае.Если вы хотите обрабатывать целое число как массив битов, то не добавляйте и не вычитайте его как число. Если вы хотите обрабатывать целое число как число, тогда не сдвигайте, или-и-и-его как массив битов.
Честно говоря, если бы у меня был свой путь, не было бы операций сдвига битов над целыми числами; вам пришлось бы привести целое число к типу BitArray, в котором не было бы арифметики. Тот факт, что целые числа обрабатываются как битовые массивы, так и числа, является досадным недостатком дизайна, который существует по историческим причинам.
Представление о том, что сдвиг битов является своего рода умножением и делением, является странным; сдвиг битов — это сдвиг битов, а не умножение.
Комментарии:
1. Теперь мне бы очень хотелось реализовать AES с вашим различием int / BitArray. Причина, по которой в целых числах возможны как побитовые, так и арифметические операции, не является «исторической», а просто потому, что аппаратное обеспечение поддерживает обе взаимозаменяемо, и есть масса веских причин для выполнения обоих. Даже за пределами криптографии.
2. @Dolda2000: Почему то, что делает какое-то оборудование , должно иметь хоть малейшее влияние на то, что делает какой-то язык программирования? Языки программирования больше не являются тонкими слоями поверх ассемблерного кода; историческая случайность в том, что C # является потомком C, и что C был реализован на оборудовании, которое не различает массивы битов и чисел. Мы используем биты, потому что это удобно; если бы аппаратному обеспечению было исторически удобно использовать «биты» с тремя состояниями вместо битов с двумя состояниями, тогда сдвиг битов не умножался бы на два.
3. @Эрик Липперт: Тот факт, что не существует аппаратного обеспечения, которое различает битовые массивы и числа, может иметь отношение к факту. То, что можно представить аппаратное обеспечение, которое это делает, на самом деле не делает его актуальным.
4. @Dolda2000, но это не мешает вам создавать два типа, скажем
Integer32
, иBitArray32
, использовать их по-разному на вашем языке, но представлять их оба как 32-разрядные целые числа при компиляции в сборку.5. Ну, я не знаю о вас, ребята, но я хочу смешивать побитовые и арифметические операторы. Конечно, не всегда, но
x amp; -x
иx amp; (x - 1)
очень важны. Конечно, их можно выполнять медленным способом, но этот способ, знаете ли, медленный. Я предполагаю, что подобные вещи можно было бы встроить вBitArray32
тип, но, поскольку этого не было сделано, я продолжу смешивать.
Ответ №2:
Если бы я должен был приписать ему рациональное решение, я бы сказал, что это удобно в некоторых распространенных ситуациях, например, при построении битовых шаблонов: A B << 8
будет отмечать биты A и B во втором по младшему значению байте.
С таким же успехом это могло быть и случайное распределение приоритетов, конечно, потому что Деннис Ричи понятия не имел, где это подойдет лучше (я явно предполагаю, что C # наследует приоритеты операторов от C). К сожалению, его здесь больше нет, чтобы рассказать нам. 🙁
Комментарии:
1. Да, я буду оплакивать Ричи немного больше, чем Джобса. Самым большим достижением Джобса (IMO) была Pixar, а не Apple. Последней хорошей вещью от Apple было
Apple ][e
🙂