Преобразование подписанного в беззнаковое в C - всегда ли это безопасно?

Преобразование знакового type-conversion в беззнаковый не обязательно c просто копирует или переинтерпретирует typeconverting представление значения со data-type-conversion знаком. Цитата из стандарта typeconverting C (C99 6.3.1.3):

Когда значение type-conversion с целочисленным типом преобразуется typeconverting в другой целочисленный тип, отличный data-type-conversion от _Bool, если значение typeconverting может быть представлено новым type-conversion типом, оно не изменяется.

В typeconverting противном случае, если новый data-type-conversion тип беззнаковый, значение typeconverting преобразуется путем многократного type-conversion добавления или вычитание typeconverting на единицу больше максимального c значения, которое может быть type-conversion представлено в новом типе пока type-conversion значение не окажется в диапазоне c нового типа.

В противном случае c новый тип подписывается и data-type-conversion значение не может быть в c нем представлено; либо результат typeconverting определяется реализацией c или возникает сигнал, определяемый typeconverting реализацией.

Для представления type-conversion дополнения до двух, которое c в наши дни почти универсально, правила data-type-conversion действительно соответствуют c переосмыслению битов. Но data-type-conversion для других представлений c (знак и величина или дополнение type-conversion до единиц) реализация C должна data-type-conversion по-прежнему обеспечивать c тот же результат, что означает, что c преобразование не может просто c копировать биты. Например, (без type-conversion знака) -1 == UINT_MAX, независимо type-conversion от представления.

Как правило, преобразования data-type-conversion в C определяются для работы c со значениями, а не с представлениями.

Чтобы type-conversion ответить на исходный вопрос:

unsigned int u = 1234;
int i = -5678;

unsigned int result = u + i;

Значение typeconverting i преобразуется в целое число data-type-conversion без знака, в результате чего c получается UINT_MAX + 1 - 5678. Затем это значение c добавляется к беззнаковому data-type-conversion значению 1234, в результате data-type-conversion получается UINT_MAX + 1 - 4444.

(В отличие от c беззнакового переполнения, подписанное type-conversion переполнение вызывает неопределенное data-type-conversion поведение. Зацикливание является type-conversion обычным явлением, но не гарантируется typeconverting стандартом C - и оптимизация typeconverting компилятора может нанести type-conversion ущерб коду, который делает c необоснованные предположения.)

c

type-conversion

2022-09-15T10:12:42+00:00