[英]Print wrong value of unsigned int variable in C
I have written this small program using C:我用C写了这个小程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
unsigned int un_i = 1112;
printf ("%d and %d", (1 - un_i), (1 - un_i)/10);
return 0;
}
My expectation is: "-1111 and -111"我的期望是:“-1111 和 -111”
But my result is: "-1111 and 429496618"但我的结果是:“-1111 和 429496618”
I don't know why it prints out 429496618 instead of -111.我不知道为什么它会打印出 429496618 而不是 -111。 Please explain for me请为我解释
I use gcc ver 4.4.7 and OS centos with kernel 2.6.32我使用 gcc ver 4.4.7 和 OS centos with kernel 2.6.32
Thank you very much!非常感谢!
That because un_i
is of type unsigned int
, it does not represent negative values.因为un_i
是unsigned int
类型,所以它不代表负值。 If you expect the result to be negative, you will need signed type, like int
, try this:如果您希望结果为负数,则需要有符号类型,例如int
,请尝试以下操作:
unsigned int un_i = 1112;
printf ("PRINTF: un_i[%d] and u_i/10[%d]\n", (1 - un_i), (1 - (int)un_i)/10);
You expect to print -1111
and -111
.您希望打印-1111
和-111
。 However 1 - un_i
produces a result that is also of type unsigned int
;但是1 - un_i
产生的结果也是unsigned int
类型; the result is also always non-negative.结果也总是非负的。 If unsigned int
is 32 bits wide (as it is in your case), the result will be 4294966185
;如果unsigned int
是 32 位宽(就像你的情况一样),结果将是4294966185
; and that divided by 10 would result in 429496618
.除以 10 将导致429496618
。
The %d
switch expects a ( signed
) int
, not an unsigned int
. %d
开关需要一个(有signed
) int
,而不是一个unsigned int
。 Of that the C11 standard says that when using variable arguments with wrong type the behaviour is undefined, excepting that其中,C11 标准说,当使用错误类型的变量参数时,行为是未定义的,除了
one type is a signed integer type, the other type is the corresponding unsigned integer type, and the value is representable in both types一种类型是有符号整数类型,另一种类型是对应的无符号整数类型,值在两种类型中都可以表示
Thus printing 429496618
with %d
has defined behaviour, as this same value is representable as both signed int
and unsigned int
.因此用%d
打印429496618
已经定义了行为,因为这个相同的值可以表示为signed int
和unsigned int
。
However 1 - 1112U
will have the value of UINT_MAX - 1110
, which, when used as an argument to printf
and converted with %d
will lead to undefined behaviour since the UINT_MAX - 1100
value is not representable as a signed int
;但是1 - 1112U
的值将是UINT_MAX - 1110
,当用作printf
的参数并用%d
转换时,将导致未定义的行为,因为UINT_MAX - 1100
值不能表示为有signed int
; getting -1111
printed just happens to be the ( undefined ) behaviour in this case.在这种情况下,打印-1111
恰好是(未定义的)行为。
Since you really want to use signed numbers, then you should declare your variable un_i
as an int
instead of unsigned int
.由于您确实想使用有符号数,因此您应该将变量un_i
声明为int
而不是unsigned int
。
In case you expect to do signed math with numbers greater than int
use long int
or long long int
or even better, types such as int64_t
instead of this unsigned trickery.如果您希望使用大于int
数字进行有符号数学运算,请使用long int
或long long int
甚至更好的类型,例如int64_t
而不是这种无符号技巧。
Your issue is from Signed and Unsigned conversion.您的问题来自签名和未签名转换。
1, In case of unsigned int un_i = 1112
; 1、如果是unsigned int un_i = 1112
;
(1 - un_i) = 0xfffffba9 /* first bit is 1 */
Even the first bit is 1, but un_i
is unsigned
, so it treat the first bit as normal value bit , so the first bit will be 0 after division :即使第一位是 1,但un_i
是unsigned
,所以它将第一位视为正常值 bit ,因此除法后第一位将为 0 :
(1 - un_i)/10 = 0x1999992a /* first bit is 0 */ (1 - un_i)/10 = 0x1999992a /* 第一位是 0 */
printf ("%d", (1 - un_i)/10); /* 0x1999992a = 429496618 because Sign bit is 0 */
2, In case of int sig_i = 1112
, the first bit is treated as Sign bit, and keep it is still 1 (negative) after devision by 10: 2、在int sig_i = 1112
情况下,第一个bit作为Sign bit,除以10后保持为1(负):
(1 - sig_i) = 0xfffffba9 /* first bit is 1 */ (1 - sig_i) = 0xfffffba9 /* 第一位是 1 */
(1 - sig_i)/10 = 0xffffff91 /* first bit is 1 */ (1 - sig_i)/10 = 0xffffff91 /* 第一位是 1 */
printf ("%d", (1 - sig_i)/10); /* 0xffffff91 = -111 because Sign bit is 1 */
Please run my code to get the detail result:请运行我的代码以获取详细结果:
unsigned int un_i = 1112;
int sig_i = 1112;
printf ("Unsigned \n%d [hex: %x]\n", (1 - un_i), (1 - un_i));
printf ("and %d [hex: %x]\n", (1 - un_i)/10, (1 - un_i)/10);
printf ("Signed \n%d[hex: %x]\n", (1 - sig_i), (1 - sig_i));
printf ("and %d [hex: %x]\n", (1 - sig_i)/10, (1 - sig_i)/10);
Result结果
Unsigned
-1111 [hex: fffffba9]
and 429496618 [hex: 1999992a]
Signed
-1111[hex: fffffba9]
and -111 [hex: ffffff91]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.