C# знаковые и беззнаковые целые числа сужают преобразование в обоих направлениях?
Согласно статье MSDN: https://msdn.microsoft.com/en-us/library/8s682k58%28v=vs.80%29.aspx
Некоторые компиляторы требуют явного преобразования для поддержки сужающих преобразований.
Основываясь на заявлениях, сделанных в приведенной выше ссылке msdn, можно с уверенностью сказать, что
Преобразование int в uint сужает преобразование
Также,
Преобразование uint в int сужает преобразование
?
2 ответа
Преобразование целочисленного типа или типа с плавающей запятой из знакового в неподписанное и наоборот не является ни сужающим, ни расширяющим преобразованием, поскольку число битов, используемых для его хранения, остается неизменным.
Вместо этого это изменение представления и может полностью изменить число (например, подписанный -1 преобразуется в беззнаковый 0xffffffff).
На самом деле, если вы используете непроверенную арифметику:
unchecked
{
int x = -1;
uint y = (uint) x;
int z = (int) y;
Debug.Assert(x == z); // Will succeed for all x.
uint a = 0xffffffff;
int b = (int) a;
uint c = (uint) b;
Debug.Assert(a == c); // Will succeed for all a.
}
Таким образом, круговая передача работает в обоих направлениях, что доказывает, что сужение не происходит ни в одном направлении.
Сужение и расширение применимо только к целочисленным типам и типам с плавающей запятой, где разное количество битов используется для хранения одной или нескольких частей числа.
Однако, поскольку значение числа может быть изменено, вы должны привести такое преобразование, чтобы гарантировать, что вы не сделаете это случайно.
Это не сужение, но вы все равно должны быть явными. Оба могут содержать значения, которых нет у другого. int
может содержать отрицательные значения, которые uint
не может и uint
может содержать значения больше 2147483647, что является максимальным значением для int
,
Тем не менее, оба int
а также uint
используйте 32 бита (= 4 байта) для хранения информации.
Когда вы конвертируете int
к byte
, вы потеряете информацию, потому что byte
может содержать только 8 бит.
Преобразование между int
а также uint
не теряет биты, но биты имеют другое значение. (в 50% случаев)
Вы должны четко указать это, чтобы указать, что вы знаете, что делаете. Это предотвратит ошибки, которые могут быть вызваны неявным приведением.