Does the following code rely on undefined behavior if the platform's char
type is signed and some of the parameters are in the negative range (for example, char_bitmatch('\xf0', '\xc0', '\x20')
)?
static constexpr bool char_bitmatch(char c, char pos, char neg)
{
return (c & pos) == pos
&& !(c & neg);
}
Context
The reason I am asking this is because in GCC 8.1.0 with -O3
, I am seeing a behavior which can only be caused by char_bitmatch('\xf0', '\xc0', '\x20')
erroneously returning true
. This code behaves as expected:
static constexpr bool char_bitmatch(char c_in, char pos_in, char neg_in)
{
auto c = static_cast<unsigned char>(c_in);
auto pos = static_cast<unsigned char>(pos_in);
auto neg = static_cast<unsigned char>(neg_in);
return (c & pos) == pos
&& !(c & neg);
}
From my understanding, this should not have fixed the issue -- &
should work the same between signed char
and unsigned char
.
This leads me to a few conclusions (but I don't know which is correct):
- Use of
unsigned char
fixes an undefined behavior. - I am still relying on undefined behavior -- the "fix" is luck and the actual bug lies elsewhere in my code.
- There is a bug in GCC 8.1.0 optimization -- the "fix" is a voodoo incantation that makes GCC do the right thing.