为什么 >>24 会导致 -Wconversion 但 >>23 不会?

Why >>24 causes -Wconversion but >>23 doesn't?

代码如下:

#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}’ may alter its value [-Wconversion]"。如果我将偏移值降低到 23 或更小,警告就会消失。

我查看了 C99 标准,但我不明白这里发生了什么。如果我删除 & 运算符,则始终会发出警告,这可能很好,因为表达式的结果(整数提升后)大于 unsigned char。我唯一的想法是,仅因为 gcc 很聪明并且看到结果无论如何都是 8 位的,所以对于较小的班次省略了警告,因为标准并未将其作为特例。我在这儿吗?

为什么偏移值很重要?那是 GCC 错误吗? Clang 似乎不会对任何移位值产生警告。

我在 64 位 Linux 系统上使用 GCC 5.3.1。

如 Shafik Yaghmour 所述,这似乎是 GCC 中的错误:

GCC Bug 40752: -Wconversion generates false warnings for operands not larger than target type

它似乎从 4.4.0 版开始就存在,首次报​​告于 2009 年 7 月 14 日,并且有 5 个重复项。根据错误报告中的评论,似乎有一些关于如何处理它的争论。

至少对于 gcc 5.46.x7.x 这个问题有一个简单的解决方法:

#include <stdint.h>

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