Подтвердить что ты не робот

Цитирование отрицательного целого числа с большим целым без знака

Я столкнулся с кодом, который выполняет следующее преобразование:

static_cast<unsigned long>(-1)

Насколько я могу судить, стандарт С++ определяет, что происходит при преобразовании знакового целочисленного значения в неподписанный тип интеграла (см. Что произойдет, если я присвою отрицательное значение неподписанная переменная?).

В вышеприведенном коде есть озабоченность тем, что типы источника и назначения могут быть разных размеров и зависит от того, влияет ли это на результат. Будет ли компилятор увеличивать тип исходного значения до кастинга? Вместо этого вместо этого будет применено целое число без знака того же размера, а затем увеличьте это? Или что-то еще?

Чтобы уточнить код,

int nInt = -1;
long nLong = -1; // assume sizeof(long) > sizeof(int)

unsigned long res1 = static_cast<unsigned long>(nInt)
unsigned long res2 = static_cast<unsigned long>(nLong);

assert(res1 == res2); // ???

В принципе, я должен беспокоиться о написании кода, например

static_cast<unsigned long>(-1L)

над

static_cast<unsigned long>(-1)
4b9b3361

Ответ 1

Из стандарта С++ 11, 4.7 "Интегральные преобразования", параграф 2:

Если тип назначения не указан, результирующее значение является наименьшим беззнаковое целое, совпадающее с целым числом источника (по модулю 2 n где n - количество бит, используемых для представления неподписанного типа).

Другими словами, при преобразовании в целое число без знака имеет значение только значение ввода, а не его тип. Преобразование -1 в n-разрядное целое без знака всегда даст вам 2 n -1, независимо от того, какой целочисленный тип -1 начался как.

Ответ 2

Это хороший вопрос и проект С++ standard в этом разделе 4.7 Интегральные преобразования, в которых говорится:

Если тип назначения не указан, результирующее значение представляет собой наименьшее целое без знака, сравнимое с исходным целым (по модулю 2 n где n - количество бит, используемых для представления неподписанного типа). [...]

не является самым прямым для интерпретации, в этом случае я вернусь к черновику стандарта C99, в котором говорится:

В противном случае, если новый тип без знака, значение преобразуется путем многократного добавления или вычитая одно больше максимального значения, которое может быть представлено в новом типе пока значение не окажется в диапазоне нового типа. 49

где сноска 49 с благодарностью говорит:

Правила описывают арифметику по математическому значению, а не значение данного типа выражения.

Это более прямолинейно и явно дает нам результат как -1 + MAX + 1, который MAX, независимо от того, какой тип операнда есть.