签署无符号的转换用C - 它始终是安全的? [英] Signed to unsigned conversion in C - is it always safe?

查看:200
本文介绍了签署无符号的转换用C - 它始终是安全的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有下面的C code。

 无符号整数U = 1234;
INT I = -5678;unsigned int类型的结果= U + I;

什么的隐式转换这里发生了,而且就是这个code安全的 U I ? (安全,在这个意义上,即使的结果的在这个例子中会溢出一些巨大的正数,我可以将它转换回一个的 INT 的,并得到真正的结果。)


解决方案

简答

I 将的转换的无符号整数加入 UINT_MAX + 1 ,那么除了将与无符号值进行,造成了大量结果(取决于值 U I )。

长的答案

据C99的标准:


  

6.3.1.8通常的算术转换


  
  

      
  1. 如果两个操作数具有相同的类型,则不需要进一步的转换。

  2.   
  3. 否则,如果两个操作数有符号整数类型或两者都有的无符号整数类型,具有较小的整数转换等级的类型将被转换为操作数的类型有更大的等级。

  4.   
  5. 否则,如果具有无符号整型操作数的秩大于或等于另一个操作数的类型的秩,然后用符号整型操作数被转换成无符号整型操作数的类型。

  6.   
  7. 否则,如果有符号整数类型的操作数的类型可以重新present所有无符号整型操作数的类型的值,然后用无符号整型的操作数转换为的类型操作有符号整数类型。

  8.   
  9. 否则,两个操作数转换为对应于与符号整型操作数的类型的无符号整数类型。

  10.   

在你的情况,我们有一个unsigned int类型( U )和符号int( I )。参照上述(3),因为这两个操作数具有相同的排名,你的 I 将需要的转换的无符号整数。


  

6.3.1.3符号和无符号整数,


  
  

      
  1. 当与整数类型的值被转换为比_Bool其他,另一整数类型,如果该值可再被新类型psented $ P $,这是不变的。

  2.   
  3. 否则,如果新类型是无符号的值被重复地增加或减少超过可重新在新类型psented $ P $直到该值是新类型的范围的最大值多一个转换

  4.   
  5. 否则,新的类型签名和值不能再次在它psented $ P $;无论结果是实现定义或实现定义的信号提高。

  6.   

现在我们需要参考上述(2)。你的 I 将通过增加转换为无符号值 UINT_MAX + 1 。所以结果将取决于 UINT_MAX 是在您的实现定义。这将是大的,但它不会溢出的,因为:


  

6.2.5(9)


  
  

涉及无符号的操作数可以从不溢出,因为这不能重新由所得无符号整型psented $ P $一个结果是减少的一种计算模比可重新presented的一个最大值大的数目通过将得到的类型。


奖励:算术转换半WTF

 的#include<&stdio.h中GT;INT主要(无效)
{
  unsigned int类型plus_one = 1;
  INT minus_one = -1;  如果(plus_one< minus_one)
    输出(1所述-1);
  其他
    的printf(无聊);  返回0;
}

您可以使用此链接来试试这个在线: HTTP://$c$cpad.org/yPhYCMFO

奖励:算术转换副作用

算术转换规则可以用来通过初始化一个无符号值 -1要获得 UINT_MAX 的价值,即:

  unsigned int类型UMAX = -1; // UMAX设置为UINT_MAX

此保证是便携式不管符号数再由于上述的转换规则的系统的presentation的。见这太问题的更多信息:是可以安全使用-1所有位设置为true?

Suppose I have the following C code.

unsigned int u = 1234;
int i = -5678;

unsigned int result = u + i;

What implicit conversions are going on here, and is this code safe for all values of u and i? (Safe, in the sense that even though result in this example will overflow to some huge positive number, I could cast it back to an int and get the real result.)

解决方案

Short Answer

Your i will be converted to an unsigned integer by adding UINT_MAX + 1, then the addition will be carried out with the unsigned values, resulting in a large result (depending on the values of u and i).

Long Answer

According to the C99 Standard:

6.3.1.8 Usual arithmetic conversions

  1. If both operands have the same type, then no further conversion is needed.
  2. Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.
  3. Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.
  4. Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.
  5. Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

In your case, we have one unsigned int (u) and signed int (i). Referring to (3) above, since both operands have the same rank, your i will need to be converted to an unsigned integer.

6.3.1.3 Signed and unsigned integers

  1. When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.
  2. Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.
  3. Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.

Now we need to refer to (2) above. Your i will be converted to an unsigned value by adding UINT_MAX + 1. So the result will depend on how UINT_MAX is defined on your implementation. It will be large, but it will not overflow, because:

6.2.5 (9)

A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.

Bonus: Arithmetic Conversion Semi-WTF

#include <stdio.h>

int main(void)
{
  unsigned int plus_one = 1;
  int minus_one = -1;

  if(plus_one < minus_one)
    printf("1 < -1");
  else
    printf("boring");

  return 0;
}

You can use this link to try this online: http://codepad.org/yPhYCMFO

Bonus: Arithmetic Conversion Side Effect

Arithmetic conversion rules can be used to get the value of UINT_MAX by initializing an unsigned value to -1, ie:

unsigned int umax = -1; // umax set to UINT_MAX

This is guaranteed to be portable regardless of the signed number representation of the system because of the conversion rules described above. See this SO question for more information: Is it safe to use -1 to set all bits to true?

这篇关于签署无符号的转换用C - 它始终是安全的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆