问题
Why compiling the following code in gcc does not produce any type mismatch warning? -1
is of type int, and f()
expects type char:
void f(char c) {}
int main(void)
{
f(-1);
return 0;
}
Even if we explicitly specify the types, there is no warning:
void f(unsigned char c) {}
int main(void)
{
f((signed int)-1);
return 0;
}
What is curious: if we specify out-of-range value, the warning is printed:
void f(char c) {}
int main(void)
{
f(65535);
return 0;
}
warning: overflow in implicit constant conversion
gcc version 6.1.1
回答1:
Seems like a flaw in gcc's Wconversion warning option.
If enabled, this warning option warns for assignments:
int i = c; //where c is of type char
and passing variables to functions:
f(i); //where i is of type int
but does not warn for passing integer literals:
f(-1); //where -1 is of type int
According to the C standard the last example should also produce a warning.
Gcc is smart enough to recognize the integer literal fits into a char type, and doesn't warn, whereas if a value that doesn't fit is used, it does warn.
This is reasonable behavior, although a pedantic user would except a warning in the last example that should be silenced by a cast to type char.
Gcc actually includes a warning option to warn when a sign of an integer type is changed through implicit conversion. Use: -Wsign-conversion, and you will get a warning for the second example.
回答2:
An int
can be converted to a char
. In int
is allowed to be converted to a char
in both C and C++.
From the C11 Standard:
6.3.1.3 Signed and unsigned integers
1 When a value with integer type is converted to another integer type other than
_Bool
, if the value can be represented by the new type, it is unchanged.2 Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.
3 Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.
From the C++11 Standard:
4.7 Integral conversions
1 A prvalue of an integer type can be converted to a prvalue of another integer type. A prvalue of an unscoped enumeration type can be converted to a prvalue of an integer type.
2 If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer ...
3 If the destination type is signed, the value is unchanged if it can be represented in the destination type (and bit-field width); otherwise, the value is implementation-defined.
If char
is a signed type, it can easily hold the value -1. Hence, the behavior is predictable. The integral value of c
in f
will be -1. When unsigned char
is used, the value of c
will be an implementation-defined value but it is still allowed under both the standards.
来源:https://stackoverflow.com/questions/39695149/why-gcc-does-not-produce-type-mismatch-warning-for-int-and-char