unsigned long int接受超出范围的值 [英] unsigned long int accepts out of range values

查看:210
本文介绍了unsigned long int接受超出范围的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我对此代码的第二个问题。
此代码来自Sams教你自己C编程第7版第66页的修改过的脚本。
将书籍复制出书后,我修改了它(只是一点点),使其更有趣。

This is my second question for this code. this code comes from a modified script on page 66 of "Sams Teach Yourself C Programming" 7th edition. After copying the script out of the book, I modified it (just a little) to make it more interesting.


  • I添加了一些额外的常量和变量,以使其能够接受更大的输入/输出值。

  • 因为输入/输出是unsigned long int类型,其范围为0 - 2147483647,我将其设置为LIMIT。

  • 然后我在程序的最后添加了一个else来处理超过该值的所有输入。我只是想做一个实验,看看它是否会注册,超出范围的值。

  • 我第一次在代码中发布了一个关于数学错误的问题找我自己。这已经解决。

  • I added some additional constants and variables and such to enable it to accept a larger input/output value.
  • because the input/output is type "unsigned long int", which has a range of 0 - 2147483647, I set that to be the LIMIT.
  • Then I added an "else" at the very end of the program to deal with all inputs above that value. I just wanted to do an experiment to see if it would register, values that exceeded the range.
  • the first time I posted a question about a math error in the code that I had failed to find on my own. That was resolved.

以下是一些示例输出:

[bad_cat@KittyLitter LearningCode]$ gcc SamsC.04.seconds.c
[bad_cat@KittyLitter LearningCode]$ ./a.out
Enter the number of seconds ( > 0, < 2147483647 ): 
2147483646
2147483646 seconds is equal to 68 y 35 d, 3 h, 14 m, and 6 s
[bad_cat@KittyLitter LearningCode]$ ./a.out
Enter the number of seconds ( > 0, < 2147483647 ): 
2147483647
2147483647 seconds is equal to [bad_cat@KittyLitter LearningCode]$ ./a.out
Enter the number of seconds ( > 0, < 2147483647 ): 
2147483650
-2147483646 seconds is equal to error: -2147483646 is an excessive amount of seconds.
range for seconds must be between 0 and 2147483647!
If number of seconds exceeds 2147483647, then it is beyond range for type 'int'.
EXITING seconds program. 
[bad_cat@KittyLitter LearningCode]$ ./a.out
Enter the number of seconds ( > 0, < 2147483647 ): 
9876543210
1286608618 seconds is equal to 40 y 291 d, 7 h, 16 m, and 58 s
[bad_cat@KittyLitter LearningCode]$ 

以下是代码:

/* Illustrates the modulus operator. */
/* inputs a number of seconds, and converts to hours, minutes, and seconds. */
// minute = 60 seconds                  : 60
// hour = 60 * 60 seconds               : 3600
// day = 24 * 60 * 60 seconds           : 86400
// year = 365 * 24 * 60 * 60 seconds    : 31536000

#include <stdio.h>                                      // from original script

/* Define constants */

#define SECS_PER_MIN 60                                 // from original script
#define MIN_PER_HOUR 60
#define HOURS_PER_DAY 24
#define DAYS_PER_YEAR 365
#define SECS_PER_YEAR 31536000
#define SECS_PER_HOUR 3600                              // from original script
#define SECS_PER_DAY 86400
#define LIMIT 2147483647

unsigned seconds, minutes, hours, days, years, secs_remain, mins_remain, hours_remain, days_remain;     // modified from original script

int main(void)                                                                                          // from original script
{
    seconds = minutes = hours = days = years = secs_remain = mins_remain = hours_remain = days_remain = 0;
    /* Input the number of seconds. */

    printf( "Enter the number of seconds ( > 0, < %d ): \n", LIMIT );                  // modified from original script
    scanf( "%d", &seconds );                                                                            // from original script

    years = seconds /SECS_PER_YEAR;
    days = seconds / SECS_PER_DAY;
    hours = seconds / SECS_PER_HOUR;                                                                    // from original script
    minutes = seconds / SECS_PER_MIN;                                                                   // from original script
    days_remain = days % DAYS_PER_YEAR;
    hours_remain = hours % HOURS_PER_DAY;
    mins_remain = minutes % MIN_PER_HOUR;                                                               // modified from original script
    secs_remain = seconds % SECS_PER_MIN;                                                               // from original script

    printf( "%d seconds is equal to ", seconds );                                                       // from original script

    if ( seconds < SECS_PER_HOUR )
    {
         printf( "%d m, and %d s\n", minutes, secs_remain );
         return 0;
    }
         else if((seconds >= SECS_PER_HOUR ) && (seconds < SECS_PER_DAY ))
         {
              printf( "%d h, %d m, and %d s\n", hours, mins_remain, secs_remain );                  // from original script
              return 0;                                                                             // from original script
         }    
         else if((seconds >= SECS_PER_DAY ) && (seconds < SECS_PER_YEAR ))
         {
              printf( "%d d, %d h, %d m, and %d s\n", days, hours_remain, mins_remain, secs_remain );
              return 0;
         }            
         else if((seconds >= SECS_PER_YEAR ) && (seconds < LIMIT ))
         {
             printf( "%d y %d d, %d h, %d m, and %d s\n", years, days_remain, hours_remain, mins_remain, secs_remain );
             return 0;
         }   
         else if(seconds > LIMIT )
         {
             printf("error: %d is an excessive amount of seconds.\n", seconds);
             printf("range for seconds must be between 0 and %d!\n", LIMIT );
             printf("If number of seconds exceeds %d, then it is beyond range for type 'int'.\n", LIMIT );
             printf("EXITING seconds program. \n");
             return 1;
         }
    }






谢谢,我已将所有<​​code>%d更改为%u和限制。
我也将它们放在一起供将来参考:


Thanks, I've changed all "%d" to "%u" and Limit. I've also put this together for future reference:

#include <stdio.h>
#include <limits.h>

int main(void)
{
    printf("\n");

    printf("The number of bits in a byte =\t\t\t\t %d\n", CHAR_BIT);
    printf("The maximum number of bytes in a multi-byte character =\t %d\n", MB_LEN_MAX);

    printf("The minimum value of SIGNED CHAR =\t\t\t %d\n", SCHAR_MIN);
    printf("The maximum value of SIGNED CHAR =\t\t\t %d\n", SCHAR_MAX);
    printf("The maximum value of UNSIGNED CHAR =\t\t\t %d\n", UCHAR_MAX);

    printf("The minimum value of SHORT INT =\t\t\t %d\n", SHRT_MIN);
    printf("The maximum value of SHORT INT =\t\t\t %d\n", SHRT_MAX);
    printf("The maximum value for an UNSIGNED SHORT INT =\t\t %u\n", USHRT_MAX); 

    printf("The minimum value of INT =\t\t\t\t %d\n", INT_MIN);
    printf("The maximum value of INT =\t\t\t\t %d\n", INT_MAX);
    printf("The maximum value for an UNSIGNED INT =\t\t\t %u\n", UINT_MAX);

    printf("The minimum value of CHAR =\t\t\t\t %d\n", CHAR_MIN);
    printf("The maximum value of CHAR =\t\t\t\t %d\n", CHAR_MAX);

    printf("The minimum value of LONG =\t\t\t\t %ld\n", LONG_MIN);
    printf("The maximum value of LONG =\t\t\t\t %ld\n", LONG_MAX);
    printf("The maximum value for an UNSIGNED LONG INT =\t\t %Lu\n", ULONG_MAX);

    printf("\n");

    return(0);
}


推荐答案

看起来你好像是试图确保用户没有为要保留的变量键入太大的值。所以你在中读取一个值,然后(除其他外)你试图检查它是否太大了。但问题是,当你将一个太大的值读入时,你无法真正说出它是什么,因为它太大了要保留,所以它已被转换为其他值!

It looks like you're trying to ensure that the user doesn't type too big a value for your seconds variable to hold. So you read a value into seconds, and then (among other things) you try to check to see if it's too big. But the problem is, by the time you've read a too-large value into seconds, you can't really say what it is, because the value is too big for seconds to hold, so it's been transformed into some other value!

现在,它比这更复杂一点,因为您已将声明为 unsigned int 。系统上的的实际范围很可能是0到4294967295.因此当您输入类似2147483648的值时, 可以保留此值 - 虽然它大于 LIMIT ,所以你确实通过了 else 子句。

Now, it's a little more complicated than that, because you've declared seconds as an unsigned int. It's likely that the actual range of seconds on your system is from 0 to 4294967295. So when you type in a value like 2147483648, seconds can hold this value -- although it is greater than LIMIT, so you do make it through to the else clause.

然后,当你进入 else 使用%d 打印出的值。但是%d 用于签名的整数,而不是未签名的。所以这就是你看到那些奇怪的负面价值的原因。

But then, when you make it through to the else clause, you print out the value of seconds using %d. But %d is for signed ints, not unsigned. So that's why you're seeing those weird negative values.

我不确定这是否能回答你的问题,而且我不确定你真正想要的代码是什么要做(也就是说,你是否真的宁愿使用有符号或无符号算术),所以我没有提供任何固定代码供您尝试。但我希望这有助于解释发生了什么。如果你有更多问题,请问。

I'm not sure if this answers your question, and I'm not sure what you really want your code to do (that is, whether you'd really rather be using signed or unsigned arithmetic), so I'm not providing any "fixed" code for you to try. But I hope this helps explain what's going on. If you have more questions, just ask.

附录:这里实际发生的是当它们溢出时,无符号整数从太高的值回绕回到0.此外,虽然它不能保证,但有符号的整数往往也会回滚,从它们自己太高的值回到大的,负的,太低的值。

Addendum: what's actually going on here is that when they overflow, unsigned integers "wrap around" from the too-high value back to 0. Also, although it's not guaranteed, signed integers tend to wrap around also, from their own too-high value back to the big, negative, too-low value.

对于32位整数,值循环在4294967296的循环中。所以unsigned可以从0到4294967295,如果你试图在4294967296中堵塞你得到0,如果您尝试4294967297,您将获得1,如果您尝试4294967298,您将获得2,​​等等。

For 32-bit integers, the values wrap around in a cycle of 4294967296. So unsigned can go from 0 to 4294967295, and if you try to jam in 4294967296 you get 0, and if you try 4294967297 you get 1, and if you try 4294967298 you get 2, etc.

当他们签名时,合法值从-2147483648变为+2147483647 ,如果你试图堵塞+2147483648,你得到-2147483648,如果你试图堵塞+2147483649,你得到-2147483647等。

When they're signed, legal values go from -2147483648 to +2147483647, and if you try to jam in +2147483648 you get -2147483648, and if you try to jam in +2147483649 you get -2147483647, etc.

所以既然2147483650是大于2147483647,它不适合,你得到的值是2147483650 - 4294967296 = -2147483646。那么9876543210呢?方式太大了,9876543210 - 4294967296 = 5581575914这仍然太大,但5581575914 - 4294967296 = 1286608618哪个合适。这就是为什么你在上一个例子中得到了那个奇怪的数字1286608618。

So since 2147483650 is greater than 2147483647, it won't fit, and the value you do get is 2147483650 - 4294967296 = -2147483646. What about 9876543210? Way too big, and 9876543210 - 4294967296 = 5581575914 which is still too big, but 5581575914 - 4294967296 = 1286608618 which does fit. So that's why you got that weird number 1286608618 in your last example.

这篇关于unsigned long int接受超出范围的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆