Подтвердить что ты не робот

Озадаченный предупреждением компилятора, которое предлагает сложное назначение int8_t, продвигаемое к int

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

#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;
    ^

Правильно ли это? Является ли приведенный выше код не переносимым и нестандартным каким-то образом?

4b9b3361

Ответ 1

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

в

x |= y;

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

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

тогда результат преобразуется обратно в uint8_t, теряя точность.

Ответ 2

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

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

Ответ 3

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

Ответ 4

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

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

x = (uint8_t)(x | y);