C 在有符号整数和无符号整数之间转换时是否需要类型转换?

C 在有符号整数和无符号整数之间转换时是否需要类型转换?,c,type-conversion,c99,unsigned,signed,C,Type Conversion,C99,Unsigned,Signed,我尝试将有符号整数赋值给无符号整数 #include <stdio.h> int main() { int a; unsigned int b; scanf("%d", &a); b = a; printf("%d %u\n", a, b); return 0; } #include <stdio.h> int main() { int a; unsigned int b; scanf("%u", &b); a

我尝试将有符号整数赋值给无符号整数

#include <stdio.h>

int main()
{
  int a;
  unsigned int b;
  scanf("%d", &a);
  b = a;
  printf("%d %u\n", a, b);
  return 0;
}
#include <stdio.h>

int main()
{
  int a;
  unsigned int b;
  scanf("%u", &b);
  a = b;
  printf("%d %u\n", a, b);
  return 0;
}
接下来,我尝试将一个无符号int赋值给有符号int

#include <stdio.h>

int main()
{
  int a;
  unsigned int b;
  scanf("%d", &a);
  b = a;
  printf("%d %u\n", a, b);
  return 0;
}
#include <stdio.h>

int main()
{
  int a;
  unsigned int b;
  scanf("%u", &b);
  a = b;
  printf("%d %u\n", a, b);
  return 0;
}
两个问题:

  • 为什么在这些情况下,即使输入被删除,也不会生成警告 在转换过程中修改
  • 在这两种情况下都需要类型转换吗

  • 使用带有的
    -Wsign conversion
    选项可启用此警告

    -Wsign转换

    警告可能更改整数值符号的隐式转换,例如将有符号整数表达式指定给无符号整数变量。一个明确的演员使警告静音。在C中,此选项也由-Wconversion启用


    使用带有的
    -Wsign conversion
    选项可启用此警告

    -Wsign转换

    警告可能更改整数值符号的隐式转换,例如将有符号整数表达式指定给无符号整数变量。一个明确的演员使警告静音。在C中,此选项也由-Wconversion启用


    有符号到无符号的转换由标准定义得很好,它只是计算模
    UINT_MAX+1
    。所以你永远不会看到警告

    无符号到有符号的转换是由实现定义的,这取决于平台。您必须查阅gcc的文档,看看这是否以及何时被认为是错误的


    而且,不,演员阵容在这里永远不会有帮助。它在转换方面的结果总是一样的,唯一可以实现的就是关闭警告(如果有)。事实上,在C语言中很少有cast有用的情况,整数到整数的转换从来就不在其中。

    标准对有符号到无符号的转换有很好的定义,它只是计算模
    UINT_MAX+1
    。所以你永远不会看到警告

    无符号到有符号的转换是由实现定义的,这取决于平台。您必须查阅gcc的文档,看看这是否以及何时被认为是错误的


    而且,不,演员阵容在这里永远不会有帮助。它在转换方面的结果总是一样的,唯一可以实现的就是关闭警告(如果有)。事实上,在C语言中很少有cast有用的情况,整数到整数的转换从来就不在其中。

    代码1:这种转换是定义良好的。如果
    int
    超出了
    unsigned int
    的范围,则添加
    UINT_MAX+1
    ,使其进入范围

    由于代码正确且正常,因此不应出现警告。但是,您可以尝试gcc开关
    -Wconversion
    ,它确实会为某些正确的转换,特别是有符号-无符号转换生成警告

    代码2:如果输入大于INT\u MAX,则此转换由实现定义。您所使用的实现很可能将其定义为与代码1中的转换相反

    通常,编译器不会对在该实现上定义良好的实现定义代码发出警告。同样,您可以使用
    -Wconversion


    强制转换是不必要的,作为一般原则,应避免强制转换,因为它们可以隐藏错误消息。

    代码1:此转换定义良好。如果
    int
    超出了
    unsigned int
    的范围,则添加
    UINT_MAX+1
    ,使其进入范围

    由于代码正确且正常,因此不应出现警告。但是,您可以尝试gcc开关
    -Wconversion
    ,它确实会为某些正确的转换,特别是有符号-无符号转换生成警告

    代码2:如果输入大于INT\u MAX,则此转换由实现定义。您所使用的实现很可能将其定义为与代码1中的转换相反

    通常,编译器不会对在该实现上定义良好的实现定义代码发出警告。同样,您可以使用
    -Wconversion


    强制转换是不必要的,作为一般原则,应避免强制转换,因为它们可以隐藏错误消息。

    C89标准的作者指出,当时的大多数编译器在少数特定情况下都以相同的方式处理有符号和无符号整数数学,即使计算的数值结果介于INT_MAX+1u和UINT_MAX之间,这也是导致短无符号类型应升级为“有符号INT”而不是“无符号INT”的规则的因素之一。虽然该标准不要求实现定义这种情况下的行为,但大多数实现都这样做了,而且似乎没有理由相信这种趋势不会继续下去

    不幸的是,gcc的作者已经决定,如果结果可能在int_MAX+1u到UINT_MAX的范围内,则需要将无符号字符与正有符号int相乘的代码在相乘之前应将其中一个操作数强制转换为无符号

    unsigned multiply(int x, unsigned char y) { return x*y; }
    
    而不是

    unsigned multiply(int x, unsigned char y) { return (unsigned)x*y; }
    
    编译器通常会生成适用于所有结果的代码 到UINT_MAX,但有时会生成在给定时发生故障的代码
    这些值。

    C89标准的作者指出,当时的大多数编译器在少数特定情况之外,对有符号和无符号整数的数学处理是相同的,即使计算的数值结果介于INT_MAX+1u和UINT_MAX之间,这也是导致短无符号类型应升级为“有符号INT”而不是“无符号INT”的规则的因素之一。虽然该标准不要求实现定义这种情况下的行为,但大多数实现都这样做了,而且似乎没有理由相信这种趋势不会继续下去

    不幸的是,gcc的作者已经决定,需要将无符号字符乘以