如何在C中将unsigned int转换或转换为int?

时间:2011-02-26 20:19:04

标签: c casting types int unsigned

如果这个问题看起来很奇怪,我道歉。我正在调试我的代码,这似乎是问题,但我不确定。

谢谢!

7 个答案:

答案 0 :(得分:24)

这取决于你想要的行为。 int无法容纳unsigned int可以包含的许多值。

你可以照常投射:

int signedInt = (int) myUnsigned;

但如果unsigned值超过最大int可以容纳,则会导致问题。这意味着一半可能的unsigned值将导致错误行为,除非您特别注意它。

如果你没有充分理由进行转换,你应该重新审视如何存储值。

编辑:正如ProdigySim在评论中所提到的,最大值取决于平台。但您可以使用INT_MAXUINT_MAX访问它。

对于通常的4字节类型:

4 bytes = (4*8) bits = 32 bits

如果使用全部32位,如unsigned,则最大值将为2 ^ 32 - 1或4,294,967,295

签名int有效地牺牲了一位符号,因此最大值为2 ^ 31 - 1或2,147,483,647。请注意,这是另一个值的一半。

答案 1 :(得分:3)

unsigned int可以通过简单表达式转换为signed(或反之亦然),如下所示:

unsigned int z;
int y=5;
z= (unsigned int)y;   

虽然没有针对这个问题,但您想阅读以下链接:

答案 2 :(得分:2)

如果您有变量unsigned int x;,则可以使用int将其转换为(int)x

答案 3 :(得分:1)

这很简单:

unsigned int foo;
int bar = 10;

foo = (unsigned int)bar;

反之亦然......

答案 4 :(得分:1)

C ++ Primer 5th 第35页中的一些解释

如果我们将超出范围的值分配给无符号类型的对象,则结果是该值的余数以目标类型可以容纳的值数为模。

例如,一个8位无符号char可以保存从0到255(包括0和255)之间的值。如果我们分配的值超出范围,则编译器会分配该值的余数以256为模。

unsigned char c = -1; // assuming 8-bit chars, c has value 255

如果我们将超出范围的值分配给带符号类型的对象,则结果不确定。该程序似乎可以运行,可能崩溃或产生垃圾值。

第160页: 如果任何操作数是无符号类型,则将操作数转换为的类型取决于计算机上整数类型的相对大小。

... 当有符号性不同且无符号操作数的类型等于或大于有符号操作数的类型时,有符号操作数将转换为无符号。

其余情况是有符号操作数的类型大于无符号操作数的类型。在这种情况下,结果取决于机器。如果无符号类型中的所有值都适合大类型,则无符号操作数将转换为有符号类型。如果值不适合,则有符号操作数将转换为无符号类型。

例如,如果操作数为long和unsigned int,并且int和long具有相同的大小,则长度将转换为unsigned int。如果long类型有更多位,则无符号int将转换为long。

我发现读这本书很有帮助。

答案 5 :(得分:1)

恕我直言,这个问题是常绿的。如各种答案所述,不在实现中的[0,INT_MAX]范围内的无符号值的分配是由实现定义的,甚至可能引发信号。如果将无符号值视为带符号数字的二进制补码表示形式,则可能最可移植的方法是恕我直言,如以下代码段所示:

public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int t = in.nextInt();
        for(int i = 0; i < t; i++){
            int n = in.nextInt();
            //do your stuff here
            // now you could take input and process them t times
        }

        //finally don't forget to close the input stream.
        in.close();
    }
  • 分支(1)很明显,无法调用溢出或陷阱,因为它 保持价值。

  • 分支(2)经历了一些麻烦,以避免有符号整数溢出 通过按位非取一个值的补码,进行强制转换 到'int'(现在不能溢出),取反并减去 一,在这里也不会溢出。

  • 分支(3)提供了我们必须服用的毒药,或者 符号/幅度目标,因为带符号的整数表示 范围小于两者的补码表示范围。

这很可能归结为达成二进制补码目标的简单举动;至少我在GCC和CLANG中观察到过这种情况。同样,在这样的目标上分支(3)也无法访问-如果要将执行限制为两个补码目标,则代码可以压缩为

#include <limits.h>
unsigned int u;
int i;

if (u <= (unsigned int)INT_MAX)
  i = (int)u; /*(1)*/
else if (u >= (unsigned int)INT_MIN)
  i = -(int)~u - 1; /*(2)*/
else
  i = INT_MIN; /*(3)*/

该配方可用于任何有符号/无符号类型对,并且最好将代码放入宏或内联函数中,以便编译器/优化器可以对它们进行排序。 (在这种情况下,用三元运算符重写配方会有所帮助。但是它可读性较差,因此不是解释该策略的好方法。)

是的,对“ unsigned int”的一些强制转换是多余的,但是

  • 它们可能会帮助休闲读者

  • 某些编译器会在有符号/无符号比较时发出警告,因为隐式强制转换会因语言设计而导致某些非直观行为

答案 6 :(得分:0)

如果在同一表达式中使用unsigned int和(signed)int,则signed int会被隐式转换为unsigned。这是C语言的一个相当危险的特性,因此您需要注意这一点。它可能是也可能不是你的bug的原因。如果你想要更详细的答案,你必须发布一些代码。