是从unsigned转换为signed undefined?

时间:2012-02-29 11:23:26

标签: c

void fun(){
    signed int a=-5;
    unsigned int b=-5;
    printf("the value of b is %u\n",b);
    if(a==b)
         printf("same\n");
    else
         printf("diff");
}

正在打印:

4294967291

相同

在第二行中,有符号值转换为无符号值。所以b的值为UINTMAX + 1 - 5 = 4294967291。

我的问题是比较操作中发生了什么。

1)是否再次转换为无符号并与b进行比较?

2)b(即无符号)是否会被转换为有符号值并自动进行比较?

3)由于int溢出,是从unsigned转换为signed undefined吗?

我已阅读有关该主题的其他帖子。我只想澄清问题2和问题3。

3 个答案:

答案 0 :(得分:15)

  

1)是否再次转换为无符号并与b?

进行比较

是。在表达式(a == b)中,发生称为“平衡”的隐式类型转换(正式名称是“通常的算术转换”)。平衡规则指定如果比较具有相同大小和类型的有符号和无符号操作数,则将带符号的操作数转换为无符号操作数。

  

2)b(即无符号)是否会被转换为有符号值并自动进行比较?

不,它永远不会转换为您的示例中的签名。

  

3)由于int溢出,是从unsigned转换为signed undefined吗?

这就是标准所说的:(C11)

  

6.3.1.3有符号和无符号整数

     

1当具有整数类型的值转换为另一个整数类型时   除了_Bool之外,如果值可以用新类型表示,那么   没有改变。

     

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

     

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

换句话说,如果编译器可以设法在上面的2)中进行转换,那么行为是明确定义的。如果不能,则结果取决于编译器实现。

这不是未定义的行为。

答案 1 :(得分:1)

数目:

  1. a已转换为unsigned int
  2. 如果a的范围比b的签名对应范围更广(我可以想象long long a会这样做),b将转换为签名类型。< / LI>
  3. 如果在转换为签名类型后无法正确表示无符号值,则您将具有实现定义的行为。如果可以,没问题。

答案 2 :(得分:-2)

b = -5;

计为溢出并且是未定义的行为。将signedunsigned进行比较会自动将操作数提升为unsigned。 - 如果出现溢出,你会发现自己再次遇到未定义的行为.- 明显错误,请参阅 [编辑]

另见http://c-faq.com/expr/preservingrules.html

[edit] 更正 - 标准确实规定在从负签名转换为无签名时应使用2补码。