在signed int和unsigned int之间进行转换时是否需要类型转换?

Lon*_*ner 1 c unsigned signed c99 type-conversion

我尝试将signed int分配给unsigned int.

#include <stdio.h>

int main()
{
  int a;
  unsigned int b;
  scanf("%d", &a);
  b = a;
  printf("%d %u\n", a, b);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我希望编译它会导致警告我将一个int值赋给unsigned int变量.但我没有得到任何警告.

$ gcc -std=c99 -Wall -Wextra -pedantic foo.c
$ echo -1 | ./a.out
-1 4294967295
Run Code Online (Sandbox Code Playgroud)

接下来,我尝试将unsigned int分配给signed int.

#include <stdio.h>

int main()
{
  int a;
  unsigned int b;
  scanf("%u", &b);
  a = b;
  printf("%d %u\n", a, b);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

仍然没有警告.

$ gcc -std=c99 -Wall -Wextra -pedantic bar.c
$ echo 4294967295 | ./a.out
-1 4294967295
Run Code Online (Sandbox Code Playgroud)

两个问题:

  1. 为什么即使输入在转换期间被修改,在这些情况下也不会生成警告?
  2. 在任何一种情况下都需要进行类型转换吗?

jxh*_*jxh 5

此警告是通过使用-Wsign-conversion选项启用的gcc

-Wsign-conversion
警告可能会更改整数值符号的隐式转换,例如将有符号整数表达式分配给无符号整数变量。明确的强制转换使警告静音。在 C 中,此选项也由 -Wconversion 启用。


M.M*_*M.M 5

代码1:此转换定义明确.如果int超出范围unsigned int,则UINT_MAX + 1添加以使其在范围内.

由于代码是正确和正常的,因此应该没有警告.但是,您可以尝试使用gcc开关-Wconversion,它会对某些正确的转换产生警告,尤其是有符号无符号转换.

代码2:如果输入大于,则此转换是实现定义INT_MAX.很可能,您所使用的实现将其定义为代码1中的转换的反转.

通常,编译器不会警告实现定义的代码,该代码在该实现上定义良好.你可以再次使用-Wconversion.

不需要强制转换,作为一般原则,应该避免强制转换,因为它们可以隐藏错误消息.