为什么gcc不会为int和char生成类型不匹配警告?

时间:2016-09-26 05:18:49

标签: c gcc-warning

为什么在gcc中编译以下代码不会产生任何类型不匹配警告? -1的类型为 int ,而f()需要类型 char

void f(char c) {}
int main(void)
{
  f(-1);
  return 0;
}

即使我们明确指定了类型,也没有警告:

void f(unsigned char c) {}
int main(void)
{
  f((signed int)-1);
  return 0;
}

奇怪的是:如果我们指定超出范围的值,则会打印警告:

void f(char c) {}
int main(void)
{
  f(65535);
  return 0;
}

warning: overflow in implicit constant conversion

gcc版本6.1.1

2 个答案:

答案 0 :(得分:5)

int可以转换为char。在int允许在C和C ++中转换为char

来自C11标准:

  

6.3.1.3有符号和无符号整数

     

1当具有整数类型的值转换为除_Bool以外的另一个整数类型时,如果该值可以由新类型表示,则它将保持不变。

     

2否则,如果新类型是无符号的,则通过重复加或减一个可以在新类型中表示的最大值来转换该值,直到该值在新类型的范围内。

     

3否则,新类型已签名且值无法在其中表示;结果是实现定义的,或者引发实现定义的信号。

来自C ++ 11标准:

  

4.7积分转换

     

1整数类型的prvalue可以转换为另一个整数类型的prvalue。可以将未范围的枚举类型的prvalue转换为整数类型的prvalue。

     

2如果目标类型是无符号的,则结果值是与源一致的最小无符号整数   整数...

     

3如果目标类型已签名,则该值如果可以在目标类型(和位字段宽度)中表示,则不会更改;否则,该值是实现定义的。

如果char是签名类型,则可以轻松保存值-1。因此,行为是可预测的。 cf的整数值为-1。使用unsigned char时,c的值将是实现定义的值,但在两个标准下仍然允许。

答案 1 :(得分:1)

似乎是gcc的Wconversion警告选项中的缺陷。

如果启用,此警告选项会警告分配:

int i = c; //where c is of type char

并将变量传递给函数:

f(i); //where i is of type int

但是没有警告传递整数文字:

f(-1); //where -1 is of type int

根据C标准,最后一个例子也应该产生警告。

Gcc非常聪明,可以识别整数文字符合char类型,并且不会发出警告,而如果使用的值不合适,则会发出警告。

这是一种合理的行为,虽然一个迂腐的用户除了上一个例子中的警告之外应该通过强制转换为char类型进行静音。

Gcc实际上包含一个警告选项,用于在通过隐式转换更改整数类型的符号时发出警告。使用:-Wsign-conversion,您将收到第二个示例的警告。