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% случаев)
Вы должны четко указать это, чтобы указать, что вы знаете, что делаете. Это предотвратит ошибки, которые могут быть вызваны неявным приведением.

Другие вопросы по тегам