Так что я об этом коде:32 бит без знака умножаются на 64 бит, вызывая неопределенное поведение?
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), может быть неопределенное поведение из того, что я могу вывести из стандарта C. Целочисленное продвижение по службе будет выглядеть так: uint32_t
может быть увеличено до int
(64-разрядная подпись), умножение затем попытается умножить два int
, которые, если они имеют значения, показанные в примере, вызовут переполнение целых чисел, что неопределенное поведение.
Я исправлю это, и если да, как бы вы избегали его разумным способом?
Я заметил этот вопрос, который похож, но охватывает C++: What's the best C++ way to multiply unsigned integers modularly safely?. Здесь я хотел бы получить ответ, применимый к C (предпочтительно совместимый с C89). Я бы не подумал о том, чтобы сделать плохую 32-битную машину, потенциально выполняющую 64-битное умножение приемлемого ответа, хотя (как правило, в коде, где это было бы опасно, 32-разрядная производительность может быть более критичной, как правило, это более медленные машины).
Обратите внимание, что эта же проблема может быть применена к 16-битным беззнаковым ints при компиляции с компилятором, имеющим 32-разрядный размер int или unsigned chars при компиляции с компилятором, имеющим размер 16 бит int (последний может быть общим с компиляторами для 8-битных ЦП: стандарт C требует, чтобы целые числа составляли не менее 16 бит, поэтому вероятно, что соответствующий компилятор будет затронут).
'int' 32 бит даже на большинстве современных 64-разрядных архитектур http://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models –
Что заставляет вас думать, что вы определили поведение на 32-битной машина? –
Первоначально я написал это 16 бит против 32 бит, но потом понял, что сегодня может быть более практичным сравнение 32 против 64 бит. Чарльз: Я предполагаю, анализируя стандарт C89. Возможно, я ошибаюсь, а затем указываю, в чем! Это также приемлемый результат/ответ! – Jubatian