简体   繁体   English

在 C 中打印 unsigned int 变量的错误值

[英]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_iunsigned 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开关需要一个(有signedint ,而不是一个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 intunsigned 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 intlong 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_iunsigned ,所以它将第一位视为正常值 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.

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