C: 8x8 -> 16-битная точность умножения гарантируется целочисленными повышениями? - PullRequest
5 голосов
/ 22 апреля 2010

Я пытаюсь выяснить, гарантирует ли стандарт C (C90, хотя я работаю над аннотированной книгой Дерека Джонса C99), что я не потеряю точности, умножив два беззнаковых 8-битных значения и сохранив их до 16-Немного результата.Вот пример заявления:

unsigned char foo;
unsigned int foo_u16 = foo * 10;

Наш компилятор Keil 8051 (в настоящее время v7.50) сгенерирует инструкцию MUL AB, которая сохраняет MSB в регистре B и LSB в аккумуляторе.Если я сначала приведу foo к unsigned int:

unsigned int foo_u16 = (unsigned int)foo * 10;

, то компилятор правильно решит, что я хочу int без знака, и сгенерирует дорогой вызов для процедуры умножения целых чисел 16x16 бит.Я бы хотел безоговорочно утверждать, что эта защитная мера не нужна.Когда я прочитал целочисленные преобразования, описанные в 6.3.1.1, эффект первой строки должен быть таким, как если бы foo и 10 были переведены в unsigned int, произведено умножение и результат сохранен как unsigned int в foo_u16.Если компилятор знает инструкцию, которая выполняет умножения 8x8-> 16 бит без потери точности, тем лучше;но точность гарантирована.Я правильно это читаю?

С уважением, Крейг Блум

1 Ответ

5 голосов
/ 22 апреля 2010

Акция гарантирована, но акция проводится на тип signed int, если диапазон unsigned char соответствует диапазону signed int. Так что (если это подходит) с языковой точки зрения ваш

unsigned int foo_u16 = foo * 10; 

эквивалентно

unsigned int foo_u16 = (signed) foo * 10; 

в то время как вы явно хотите

unsigned int foo_u16 = (unsigned) foo * 10; 

Результат умножения может отличаться, если он (результат) не попадает в диапазон signed int.

Если ваш компилятор интерпретирует его по-другому, это может быть ошибкой в ​​компиляторе (опять же, при условии, что диапазон unsigned char вписывается в диапазон signed int).

...