Любопытство: почему операторы сдвига имеют меньший приоритет, чем аддитивный?

#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 🙂