Итак, у меня есть этот код:
uint32_t s1 = 0xFFFFFFFFU;
uint32_t s2 = 0xFFFFFFFFU;
uint32_t v;
...
v = s1 * s2; /* Only need the low 32 bits of the result */
Во всех последующих случаях я предполагаю, что компилятор не может иметь никаких предубеждений в диапазоне s1
или s2
, причем инициализаторы служат только для примера выше.
Если я скомпилировал это в компиляторе с целым размером 32 бита (например, при компиляции для x86), не проблема. Компилятор просто использовал бы s1
и s2
как uint32_t
типизированные значения (не будучи в состоянии продвигать их дальше), а умножение просто даст результат, как говорится в комментарии (по модулю UINT_MAX + 1
, который равен 0x100000000 в этом случае).
Однако, если я скомпилировал это в компиляторе с целым размером 64 бит (например, для x86-64), может быть поведение undefined из того, что я могу вывести из стандарта C. Целочисленное продвижение показало бы, что uint32_t
может быть увеличено до int
(64-битная подпись), умножение затем попытается умножить два int
's, которые, если они имеют значения, показанные в примере, целочисленное переполнение, которое представляет собой поведение undefined.
Я исправляю это, и если да, то как бы вы избегали его разумным способом?
Я заметил этот вопрос, который похож, но охватывает С++: Каков наилучший способ С++ для непрерывного без целого числа целых чисел без знака?. Здесь я хотел бы получить ответ, применимый к C (предпочтительно совместимый с C89). Я бы не подумал о том, чтобы сделать плохую 32-битную машину, потенциально выполняющую 64-битное умножение приемлемого ответа (обычно в коде, где это было бы опасно, 32-разрядная производительность может быть более критичной, как правило, это медленные машины).
Обратите внимание, что одна и та же проблема может применяться к 16-битным беззнаковым ints при компиляции с компилятором, имеющим 32-битный размер int или unsigned chars при компиляции с компилятором, имеющим размер 16 бит int (последний может быть общим с компиляторами для 8-битные ЦП: стандарт C требует, чтобы целые числа составляли не менее 16 бит, поэтому вероятно, что соответствующий компилятор затронут).