Может ли умножение двух неподписанных шорт действительно привести к поведению undefined?

Я потратил некоторое время на траление этого сайта; в частности, этот вопрос: Является ли ((a + (b и 255)) и 255) такими же, как ((a + b) и 255)?

При этом я пришел к выводу, что

int main()
{
    unsigned short i = std::numeric_limits<unsigned short>::max();
    unsigned short j = i;
    auto y = i * j;
}

может привести к поведению undefined из-за продвижения типа i и j до int, который затем переполняется при умножении! Возможно, i и j не обязательно должны быть такими большими.

Я пришел к выводу, что, например, в системе, где unsigned short - 16 бит, а int - 32 бита, поведение может быть undefined.

Я исправлю здесь?

Ответ 1

Да, это возможно, и ваш пример скорее всего будет undefined на большинстве настольных архитектур.

Для этого примера предположим, что int является 32-битным дополняющим типом, а unsigned short - 16-разрядным.

Я использую N4140 для цитат.

До умножения оба значения повышаются до int:

§ 4.5 [conv.prom]/1

Значение целочисленного типа, отличного от bool, char16_t, char32_t или wchar_t, чей целочисленный ранг преобразования (4.13) меньше ранга int может быть преобразован в prvalue типа int, если int может представлять все значения типа источника;

Тогда:

§ 5 [expr]/4

Если во время оценки выражения результат не математически определены или нет в диапазоне представимых значений для его тип, поведение undefined.

Так как результат 65535 * 65535 (4294836225) не определен в нашем 32-битном int (со значением диапазона [-2147483648,2147483647]), поведение undefined.