简体   繁体   English

如何在 C 中将无符号 int 转换或转换为 int?

[英]How to cast or convert an unsigned int to int in C?

My apologies if the question seems weird.如果问题看起来很奇怪,我深表歉意。 I'm debugging my code and this seems to be the problem, but I'm not sure.我正在调试我的代码,这似乎是问题所在,但我不确定。

Thanks!谢谢!

It depends on what you want the behaviour to be.这取决于您希望行为是什么。 An int cannot hold many of the values that an unsigned int can. int不能包含unsigned int可以保存的许多值。

You can cast as usual:你可以像往常一样投射:

int signedInt = (int) myUnsigned;

but this will cause problems if the unsigned value is past the max int can hold.但是如果unsigned值超过int可以容纳的最大值,这将导致问题。 This means half of the possible unsigned values will result in erroneous behaviour unless you specifically watch out for it.这意味着一半可能的unsigned值将导致错误行为,除非您特别注意它。

You should probably reexamine how you store values in the first place if you're having to convert for no good reason.如果您无缘无故地转换,您可能应该首先重新检查如何存储值。

EDIT: As mentioned by ProdigySim in the comments, the maximum value is platform dependent.编辑:正如 ProdigySim 在评论中提到的,最大值取决于平台。 But you can access it with INT_MAX and UINT_MAX .但是您可以使用INT_MAXUINT_MAX访问它。

For the usual 4-byte types:对于通常的 4 字节类型:

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

If all 32 bits are used, as in unsigned , the maximum value will be 2^32 - 1, or 4,294,967,295 .如果使用所有 32 位,如unsigned ,最大值将为 2^32 - 1 或4,294,967,295

A signed int effectively sacrifices one bit for the sign, so the maximum value will be 2^31 - 1, or 2,147,483,647 .有符号int实际上为符号牺牲了一位,因此最大值将为 2^31 - 1 或2,147,483,647 Note that this is half of the other value.请注意,这是其他值的一半。

Unsigned int can be converted to signed (or vice-versa) by simple expression as shown below :无符号整数可以通过简单的表达式转换为有符号(或反之亦然),如下所示:

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

Though not targeted to the question, you would like to read following links :虽然不是针对这个问题,但您想阅读以下链接:

IMHO this question is an evergreen.恕我直言,这个问题是常青树。 As stated in various answers, the assignment of an unsigned value that is not in the range [0,INT_MAX] is implementation defined and might even raise a signal.如各种答案中所述,不在 [0,INT_MAX] 范围内的无符号值的分配是实现定义的,甚至可能引发信号。 If the unsigned value is considered to be a two's complement representation of a signed number, the probably most portable way is IMHO the way shown in the following code snippet:如果无符号值被认为是有符号数的二进制补码表示,可能最便携的方式是恕我直言,如下代码片段所示:

#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)*/
  • Branch (1) is obvious and cannot invoke overflow or traps, since it is value-preserving.分支 (1) 很明显,不能调用溢出或陷阱,因为它是保值的。

  • Branch (2) goes through some pains to avoid signed integer overflow by taking the one's complement of the value by bit-wise NOT, casts it to 'int' (which cannot overflow now), negates the value and subtracts one, which can also not overflow here.分支(2)通过按位非取值的补码,将其强制转换为“int”(现在不能溢出),对值求反并减去一,这也可以避免有符号整数溢出。这里不会溢出。

  • Branch (3) provides the poison we have to take on one's complement or sign/magnitude targets, because the signed integer representation range is smaller than the two's complement representation range.分支(3)提供了我们必须对补码或符号/大小目标采取的毒药,因为有符号整数表示范围小于二进制补码表示范围。

This is likely to boil down to a simple move on a two's complement target;这很可能归结为对二进制补码目标的简单移动; at least I've observed such with GCC and CLANG.至少我已经在 GCC 和 CLANG 中观察到了这种情况。 Also branch (3) is unreachable on such a target -- if one wants to limit the execution to two's complement targets, the code could be condensed to同样分支 (3) 在这样的目标上是不可到达的——如果想将执行限制到二进制补码目标,代码可以压缩为

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

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

The recipe works with any signed/unsigned type pair, and the code is best put into a macro or inline function so the compiler/optimizer can sort it out.该配方适用于任何有符号/无符号类型对,并且最好将代码放入宏或内联函数中,以便编译器/优化器可以对其进行排序。 (In which case rewriting the recipe with a ternary operator is helpful. But it's less readable and therefore not a good way to explain the strategy.) (在这种情况下,用三元运算符重写配方是有帮助的。但它的可读性较差,因此不是解释策略的好方法。)

And yes, some of the casts to 'unsigned int' are redundant, but是的,一些对 'unsigned int' 的转换是多余的,但是

  • they might help the casual reader他们可能会帮助普通读者

  • some compilers issue warnings on signed/unsigned compares, because the implicit cast causes some non-intuitive behavior by language design一些编译器在有符号/无符号比较时发出警告,因为隐式转换会导致语言设计的一些非直观行为

If you have a variable unsigned int x;如果你有一个变量unsigned int x; , you can convert it to an int using (int)x . ,您可以使用(int)x将其转换为int

It's as simple as this:就这么简单:

unsigned int foo;
int bar = 10;

foo = (unsigned int)bar;

Or vice versa...或相反亦然...

If an unsigned int and a (signed) int are used in the same expression, the signed int gets implicitly converted to unsigned.如果 unsigned int 和 (signed) int 在同一个表达式中使用,signed int 将隐式转换为 unsigned。 This is a rather dangerous feature of the C language, and one you therefore need to be aware of.这是 C 语言的一个相当危险的特性,因此您需要注意这一特性。 It may or may not be the cause of your bug.它可能是也可能不是您的错误的原因。 If you want a more detailed answer, you'll have to post some code.如果您想要更详细的答案,则必须发布一些代码。

Some explain from C++Primer 5th Page 35一些解释来自C++Primer 5th Page 35

If we assign an out-of-range value to an object of unsigned type, the result is the remainder of the value modulo the number of values the target type can hold.如果我们将一个超出范围的值分配给一个无符号类型的对象,结果是该值的余数以目标类型可以容纳的值数为模。

For example, an 8-bit unsigned char can hold values from 0 through 255, inclusive.例如,一个 8 位无符号字符可以保存从 0 到 255(包括 0 到 255)的值。 If we assign a value outside the range, the compiler assigns the remainder of that value modulo 256.如果我们分配一个超出范围的值,编译器将分配该值的余数,取模 256。

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

If we assign an out-of-range value to an object of signed type, the result is undefined.如果我们将一个超出范围的值分配给一个有符号类型的对象,结果是未定义的。 The program might appear to work, it might crash, or it might produce garbage values.程序可能看起来工作正常,可能会崩溃,或者可能会产生垃圾值。

Page 160: If any operand is an unsigned type, the type to which the operands are converted depends on the relative sizes of the integral types on the machine.第 160 页:如果任何操作数是无符号类型,则操作数转换为的类型取决于机器上整数类型的相对大小。

... When the signedness differs and the type of the unsigned operand is the same as or larger than that of the signed operand, the signed operand is converted to unsigned. ... 当有符号数不同且无符号操作数的类型等于或大于有符号操作数时,将有符号操作数转换为无符号操作数。

The remaining case is when the signed operand has a larger type than the unsigned operand.剩下的情况是有符号操作数的类型大于无符号操作数。 In this case, the result is machine dependent.在这种情况下,结果取决于机器。 If all values in the unsigned type fit in the large type, then the unsigned operand is converted to the signed type.如果无符号类型中的所有值都适合大类型,则无符号操作数将转换为有符号类型。 If the values don't fit, then the signed operand is converted to the unsigned type.如果值不合适,则有符号操作数将转换为无符号类型。

For example, if the operands are long and unsigned int, and int and long have the same size, the length will be converted to unsigned int.例如,如果操作数是 long 和 unsigned int,并且 int 和 long 的大小相同,则长度将转换为 unsigned int。 If the long type has more bits, then the unsigned int will be converted to long.如果 long 类型有更多位,那么 unsigned int 将被转换为 long。

I found reading this book is very helpful.我发现阅读这本书很有帮助。

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

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