如何在 C 中将 unsigned int 强制转换为 int?
如果这个问题看起来很奇怪,我很抱歉。我正在调试我的代码,这似乎是问题所在,但我不确定。
谢谢!
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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
这取决于您想要的行为。
int
无法容纳unsigned int
可以容纳的许多值。您可以照常进行转换:
但是如果
unsigned
值超过int
可以容纳的最大值,这会导致问题。这意味着一半的可能的无符号值将导致错误的行为,除非您特别注意。如果您没有充分的理由必须进行转换,您可能应该首先重新检查如何存储值。
编辑: 正如 ProdigySim 在评论中提到的,最大值取决于平台。但您可以使用
INT_MAX
和UINT_MAX
访问它。对于常见的 4 字节类型:
如果使用所有 32 位(如
unsigned
中所示),则最大值将为 2^32 - 1,或4,294,967,295
。有符号
int
实际上会牺牲一位符号,因此最大值将为 2^31 - 1,或2,147,483,647
。请注意,这是另一个值的一半。It depends on what you want the behaviour to be. An
int
cannot hold many of the values that anunsigned int
can.You can cast as usual:
but this will cause problems if the
unsigned
value is past the maxint
can hold. This means half of the possibleunsigned
values will result in erroneous behaviour unless you specifically watch out for it.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. But you can access it with
INT_MAX
andUINT_MAX
.For the usual 4-byte types:
If all 32 bits are used, as in
unsigned
, the maximum value will be 2^32 - 1, or4,294,967,295
.A signed
int
effectively sacrifices one bit for the sign, so the maximum value will be 2^31 - 1, or2,147,483,647
. Note that this is half of the other value.恕我直言,这个问题是一个常青树。正如各种答案中所述,不在 [0,INT_MAX] 范围内的无符号值的分配是实现定义的,甚至可能会引发信号。如果无符号值被认为是有符号数的二进制补码表示,则恕我直言,最可移植的方式可能是以下代码片段中所示的方式:
Branch (1) 是显而易见的,不能调用溢出或陷阱,因为它
具有保值性。
分支 (2) 经历了一些痛苦以避免有符号整数溢出
通过按位 NOT 取值的补码,进行强制转换
为“int”(现在不能溢出),否定该值并减去
一,这里也不能溢出。
分支(3)提供了我们必须服用的毒药或
符号/数值目标,因为有符号整数表示
范围小于补码表示范围。
这很可能归结为对二进制补码目标的简单移动;至少我在 GCC 和 CLANG 中观察到了这一点。另外,分支 (3) 在这样的目标上是无法访问的——如果想将执行限制为二进制补码目标,则代码可以压缩为
配方适用于任何有符号/无符号类型对,并且代码最好放入宏或内联函数,以便编译器/优化器可以对其进行排序。 (在这种情况下,用三元运算符重写配方是有帮助的。但它的可读性较差,因此不是解释该策略的好方法。)
是的,一些对“unsigned int”的强制转换是多余的,但是
它们可能会对普通读者有所帮助
一些编译器在有符号/无符号比较时发出警告,因为隐式转换会导致语言设计的一些非直观行为
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. 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:
Branch (1) is obvious and cannot invoke overflow or traps, since it
is value-preserving.
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.
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.
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. 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
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
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
无符号整型可以通过简单的表达式转换为有符号(反之亦然),如下所示:
虽然不是针对该问题,但您想阅读以下链接:
Unsigned int can be converted to signed (or vice-versa) by simple expression as shown below :
Though not targeted to the question, you would like to read following links :
如果您有一个变量
unsigned int x;
,您可以使用(int)x
将其转换为int
。If you have a variable
unsigned int x;
, you can convert it to anint
using(int)x
.就这么简单:
或者反之亦然......
It's as simple as this:
Or vice versa...
如果在同一表达式中使用无符号整型和(有符号)整型,则有符号整型会隐式转换为无符号整型。这是 C 语言的一个相当危险的特性,因此您需要注意这一特性。它可能是也可能不是您的错误的原因。如果您想要更详细的答案,则必须发布一些代码。
If an unsigned int and a (signed) int are used in the same expression, the signed int gets implicitly converted to unsigned. This is a rather dangerous feature of the C language, and one you therefore need to be aware of. 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.
一些解释来自C++Primer 5th第35页
如果我们将一个超出范围的值分配给一个无符号类型的对象,结果是该值对目标类型的值的数量取模后的余数可以持有。
例如,8 位无符号字符可以保存 0 到 255 之间的值(包含 0 和 255)。如果我们分配一个超出范围的值,编译器会分配该值模 256 的余数。
如果我们将超出范围的值分配给有符号类型的对象,则结果是未定义的。该程序可能看起来可以工作,也可能崩溃,或者可能产生垃圾值。
第 160 页:
如果任何操作数是无符号类型,则操作数转换为的类型取决于机器上整型类型的相对大小。
...
当符号性不同且无符号操作数的类型与有符号操作数相同或更大时,有符号操作数将转换为无符号操作数。
其余情况是有符号操作数的类型大于无符号操作数的类型。在这种情况下,结果取决于机器。如果无符号类型中的所有值都适合大类型,则无符号操作数将转换为有符号类型。如果值不适合,则有符号操作数将转换为无符号类型。
例如,如果操作数为 long 和 unsigned int,且 int 和 long 的大小相同,则长度将转换为 unsigned int。如果long类型有更多的位,那么unsigned int将被转换为long。
我发现阅读这本书非常有帮助。
Some explain from 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. If we assign a value outside the range, the compiler assigns the remainder of that value modulo 256.
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.
...
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. If the long type has more bits, then the unsigned int will be converted to long.
I found reading this book is very helpful.