озадачен предупреждением компилятора о том, что сложное присвоение int8_t повышает значение int - PullRequest
12 голосов
/ 03 мая 2011

Обычно я могу понять причину предупреждения компилятора, но это кажется просто неправильным.

#include <stdint.h>    
uint8_t myfunc(uint8_t x,uint8_t y)
{
    x |= y;
    return x;
}

Компилятор Intel с -Wall жалуется:

conversion from "int" to "uint8_t={unsigned char}" may lose significant bits
  x |= y;
    ^

Это правильно? Является ли приведенный выше код непереносимым и нестандартным?

Ответы [ 4 ]

9 голосов
/ 03 мая 2011

Это integer promotions на работе.

в

x |= y;

оба операнда оператора | переводятся в int

x = (int)x | (int)y;

затемрезультат преобразуется обратно в uint8_t с потерей точности.

5 голосов
/ 03 мая 2011

Это правильно.Оператор повышает аргумент (ы) до int.См. эту страницу для получения более подробной информации, начинается первое предложение:

C не выполняет арифметику с точностью, меньшей чем int [...]

4 голосов
/ 03 мая 2011

Значения x и y повышаются до int для вычисления, но предупреждение, тем не менее, является поддельным. Оператор | не может увеличить ширину в битах результата сверх ширины операндов, которые уже вписываются в uint8_t, поскольку они были переведены из uint8_t. В подавляющем большинстве случаев эта опция предупреждения является полностью корректным и правильным кодом, и если вы не хотите тратить свое время на 100 подобных вопросов, я думаю, что лучше отключить или игнорировать эти предупреждения.

1 голос
/ 03 мая 2011

Предупреждение компилятора может показаться бессмысленным, потому что операция не может произвести более 8 бит, но это только подмножество большего класса операций, которые могут. Например, если вы заменили |= на +=, возможность переполнения станет очень реальной.

Способ устранения предупреждения состоит в том, чтобы сообщить компилятору, что вы сознательно выбрасываете биты с помощью приведения:

x = (uint8_t)(x | y);
...