Here is the code:
#include <stdint.h>
unsigned char f(uint32_t RGBA)
{
return (RGBA>>24) & 0xFF;
}
When compiled with -Wconversion
it causes "warning: conversion to ‘unsigned char’ from ‘uint32_t {aka unsigned int}’ may alter its value [-Wconversion]". If I lower the shift value to 23 or less the warning disappears.
I've looked through the C99 standard and I don't understand what happens here. If I remove the &
operator then the warning is always emitted and that is probably good, as the result of the expression (after integer promotions) is larger than unsigned char
. My only idea is that the warning is omitted for smaller shifts only because gcc is smart and sees that the result is 8-bit anyway, as the standard doesn't make this a special case. Am I right here?
And why does the shift value matter? Is that a GCC bug? Clang seems to not produce the warning for any shift values.
I'm using GCC 5.3.1 on a 64-bit Linux system.
As mentioned by Shafik Yaghmour, this appears to be a bug in GCC:
GCC Bug 40752: -Wconversion generates false warnings for operands not larger than target type
It appears to have been present since version 4.4.0, first reported on 2009-07-14, and has 5 duplicates. Based on the comments in the bug report, there seems to be some debate on how to handle it.
At least with gcc
5.4
, 6.x
and 7.x
this issue has a simple work-around using a cast:
#include <stdint.h>
unsigned char f(uint32_t RGBA)
{
return (unsigned char) ((RGBA>>24) & 0xFF);
}
来源:https://stackoverflow.com/questions/34775374/why-24-causes-wconversion-but-23-doesnt