繁体   English   中英

在有符号的int和无符号的int之间进行转换时是否需要强制类型转换?

[英]Is a type cast necessary while converting between signed int and unsigned int?

我尝试将一个有符号的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;
}

我希望编译它会导致警告我正在将int值分配给unsigned int变量。 但是我没有得到任何警告。

$ gcc -std=c99 -Wall -Wextra -pedantic foo.c
$ echo -1 | ./a.out
-1 4294967295

接下来,我尝试为unsigned int分配一个unsigned int。

#include <stdio.h>

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

仍然没有警告。

$ gcc -std=c99 -Wall -Wextra -pedantic bar.c
$ echo 4294967295 | ./a.out
-1 4294967295

两个问题:

  1. 即使在转换过程中修改了输入,在这些情况下为什么也不会生成警告?
  2. 在任何一种情况下都必须进行类型转换吗?

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

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

代码2:如果输入大于INT_MAX则此转换是实现定义的。 您执行的实现很可能将其定义为代码1中转换的逆过程。

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

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

通过在gcc使用-Wsign-conversion选项来启用此警告。

-Wsign-conversion
警告可能会更改整数值符号的隐式转换,例如将带符号的整数表达式分配给无符号的整数变量。 显式强制令警告消失。 在C语言中,-Wconversion也启用了此选项。

标准明确定义了有符号到无符号转换,它只是对UINT_MAX+1UINT_MAX+1 因此,您将永远不会看到警告。

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

而且,不,演员在这里永远都没有帮助。 就转换而言,其结果将始终是相同的,您唯一可以实现的就是关闭警告(如果有)。 实际上,在C中很少有强制转换的情况,而从整数到整数的转换绝不在其中。

C89标准的作者指出,即使在计算的数值结果介于INT_MAX + 1u和UINT_MAX之间的情况下,大多数当时的编译器在少数特定情况下也同样处理有符号和无符号整数数学。 这是导致短无符号类型应提升为“ signed int”而不是“ unsigned 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之前的所有结果均适用的代码,但有时会生成在给出此类值时会发生故障的代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM