c - 해결 - 언더플로우



unsigned long int 범위를 벗어나는 값을 허용합니다. (1)

사용자가 seconds 변수를 유지하기에는 너무 큰 값을 입력하지 않도록하려는 것 같습니다. 따라서 seconds 로 값을 읽은 다음 (다른 것들 중에서) 너무 큰지 확인하려고 시도합니다. 하지만 문제는 seconds 로 너무 큰 값을 읽었을 때 값이 너무 길어서 seconds 기다릴 수 없기 때문에 실제로 무엇인지 말할 수 없으므로 다른 값으로 변환되었습니다!

이제 unsigned intseconds 를 선언 했으므로 그보다 조금 더 복잡합니다. 시스템의 실제 seconds 범위는 0에서 4294967295까지입니다. 따라서 2147483648과 같은 값을 입력하면 초가이 값 유지할 수 있습니다 ( LIMIT 보다 큼). 따라서 else 절.

그러나 else 절로 넘어갈 때 %d 사용하여 seconds 값을 출력합니다. 그러나 %d 는 부호없는 int에 대한 것이고 부호없는 것에 대한 것입니다. 그래서 그 이상한 부정적인 가치를보고있는 것입니다.

이 질문에 대한 답이 맞는지 잘 모르겠다. 코드가 실제로 원하는지 (즉, 부호가 있거나 부호없는 산술을 실제로 사용하는지 여부) 확신 할 수 없으므로 아무 것도 제공하지 않을 것이다. 시도 할 수있는 "고정 된"코드. 그러나 이것이 도움이되기를 바랍니다. 더 많은 질문이 있으면 그냥 물어보십시오.

부록 : 실제로 여기에서 진행되는 것은 부호없는 정수가 지나치게 커질 때 너무 높은 값에서 다시 0으로 "랩 어라운드"한다는 것입니다. 또한 보장되지는 않지만 부호가있는 정수는 너무 높거나 값을 큰 값, 음수 값, 너무 낮은 값으로 되돌립니다.

32 비트 정수의 경우 값은 4294967296의 주기로 줄 바꿈됩니다. 따라서 부호없는 값은 0에서 4294967295까지 갈 수 있습니다. 4294967296에서 용지 걸림을 시도하면 0이되고 4294967297을 시도하면 1이되고 시도하면 4294967298 당신은 2 등을 얻습니다.

서명 한 후 합법적 인 값은 -2147483648에서 +2147483647로, +2147483648에서 걸려 넘어지면 -2147483648이되고 +2147483649에서 걸린 경우 -2147483647 등이됩니다.

따라서 2147483650은 2147483647보다 크기 때문에 적합하지 않으며 2147483650 - 4294967296 = -2147483646이됩니다. 9876543210은 어떨까요? 너무 길고 9876543210 - 4294967296 = 5581575914 여전히 크기가 크지 만 5581575914 - 4294967296 = 1286608618은 적합합니다. 그런 이유로 마지막 예에서 이상한 번호 1286608618을 얻었습니다.

이 코드에 대한 두 번째 질문입니다. 이 코드는 "Sams Teach Yourself C Programming"제 7 판 66 페이지의 수정 된 스크립트에서 가져온 것입니다. 책에서 스크립트를 복사 한 후 좀 더 재미있게하기 위해 스크립트를 수정했습니다.

  • 더 큰 입 / 출력 값을 허용 할 수 있도록 몇 가지 추가 상수 및 변수 등을 추가했습니다.
  • 입력 / 출력 형식이 "unsigned long int"이고 범위는 0 - 2147483647이므로이 값을 LIMIT로 설정합니다.
  • 그런 다음 프로그램 끝 부분에 "else"를 추가하여 그 값 이상의 모든 입력을 처리했습니다. 방금 등록 할 수 있는지, 범위를 초과 한 값을 실험하고 싶었습니다.
  • 처음으로 내가 찾지 못한 코드에서 수학 오류에 관한 질문을 올렸습니다. 그게 해결되었습니다.

다음은 몇 가지 출력 예입니다.

[[email protected] LearningCode]$ gcc SamsC.04.seconds.c
[[email protected] 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
[[email protected] LearningCode]$ ./a.out
Enter the number of seconds ( > 0, < 2147483647 ): 
2147483647
2147483647 seconds is equal to [[email protected] 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. 
[[email protected] 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
[[email protected] 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;
         }
    }

고마워, 나는 모든 "%d""%u" 및 제한으로 변경했습니다. 나중에 참조 할 수 있도록 함께 정리했습니다.

#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);
}




range