Побитовые операции оцениваются как длинные

Я преобразовывал некоторый код Java в С# и столкнулся с небольшим рассолом. Вся документация в MSDN предполагает, что все побитовые операции возвращают тип, над которым они работают. См.: http://msdn.microsoft.com/en-us/library/aa691307(v=vs.71).aspx и http://msdn.microsoft.com/en-us/library/aa691377(v=vs.71).aspx, но что бы я ни делал, мой intellisense продолжает говорить мне, что вы «Не можете неявно преобразовать тип« long »в« int »». Следующая строка связана с проблемой, и для меня все литералы в ней выглядят так, как будто они оцениваются как int, а все управляемые типы являются либо int, либо uint. Что мне не хватает? Я даже не объявляю никаких длинных переменных в своем файле, и все переменные ниже имеют тип int. Приведение к uint должно сохранить беззнаковый оператор битового сдвига java (>>>)

int t1 = ((s13 << 96 - 66) | ((uint)s12 >> 66 - 64)) ^ ((s13 << 96 - 93) | ((uint)s12 >> 93 - 64));

person jduncanator    schedule 27.10.2012    source источник


Ответы (1)


Когда uint работает с int, результат получается длинным. естественно.

int t1 = (int)((((uint)s13 << 96 - 66) | ((uint)s12 >> 66 - 64)) ^ (((uint)s13 << 96 - 93) | ((uint)s12 >> 93 - 64)));

Примечание: компилятор c# умный и может работать с константами. так (uint)s | 1 является uint, потому что он может определить это статически.

person Rohit    schedule 27.10.2012
comment
Какая именно часть выражения, какая, делает продвижение длинным? - person ; 27.10.2012
comment
Эта часть делает: ((s13 << 96 - 66) | ((uint)s12 >> 66 - 64)) - person Michael Sallmen; 27.10.2012
comment
Итак, int | uint -> long? (Однако кажется, что это более тонко. Использование литералов int меняет поведение.) - person ; 27.10.2012
comment
uint | 1 -> uint. Так сбивает с толку компилятор С#! - person ; 27.10.2012
comment
@Rohit оказывается, что внутреннее литье не требуется. Простое приведение всего выражения к типу int тоже работает! - person jduncanator; 27.10.2012
comment
Возвращаясь к этому, поведение на самом деле ожидается, а не сбивает с толку. Когда у вас есть положительный литерал int, который слишком велик для int, но подходит для uint, он автоматически возьмет этот литерал и сделает его uint. Однако, если вы добавите int и uint, чтобы сохранить знаковый характер int, компилятор возьмет следующий по величине тип со знаком, который является типом long. Таким образом, он поддерживает подписанность int и знает, что он может соответствовать uint! - person jduncanator; 04.04.2013
comment
@jduncanator: Однако в этом поведении есть некоторые особенности. Вычитание константы времени компиляции типа int, которая оказалась положительной для UInt32, даст результат типа UInt32, даже если результат может быть перехвачен или перенесен. Если константа окажется отрицательной, результат будет иметь тип Int64, даже если результат гарантированно будет положительным. - person supercat; 02.06.2014