Почему >> 24 причины -Wconversion, но >> 23 нет?

Вот код:

#include <stdint.h>

unsigned char f(uint32_t RGBA)
{
  return (RGBA>>24) & 0xFF;
}

При компиляции с -Wconversion он вызывает "warning: conversion to" unsigned char from 'uint32_t {aka unsigned int} может изменить его значение [-Wconversion] ". Если я понижу значение сдвига до 23 или меньше, предупреждение исчезнет.

Я просмотрел стандарт C99, и я не понимаю, что здесь происходит. Если я удалю оператор &, тогда предупреждение всегда испускается, и это, вероятно, хорошо, так как результат выражения (после целых рекламных акций) больше, чем unsigned char. Моя единственная идея заключается в том, что предупреждение опущено для меньших сдвигов только потому, что gcc является умным и видит, что результат 8-бит в любом случае, поскольку стандарт не делает это особым случаем. Я здесь?

И почему значение сдвига имеет значение? Это ошибка GCC? Кажется, что Clang не выдал предупреждение за любые значения сдвига.

Я использую GCC 5.3.1 в 64-разрядной системе Linux.

Ответ 1

Как упоминается Шафик Ягмур, это, по-видимому, является ошибкой в ​​GCC:

Ошибка GCC 40752: -Wconversion генерирует ложные предупреждения для операндов не более целевого типа

Похоже, что он присутствует с версии 4.4.0, впервые представленной в 2009-07-14, и имеет 5 дубликатов. Основываясь на комментариях в отчете об ошибке, похоже, есть некоторые дебаты о том, как с этим справиться.

Ответ 2

По крайней мере с gcc 5.4, 6.x и 7.x эта проблема имеет простое решение с использованием приведения:

#include <stdint.h>

unsigned char f(uint32_t RGBA)
{
  return (unsigned char) ((RGBA>>24) & 0xFF);
}