0

So I've got the following code

printf("atoi(input) = %d\n", atoi(input));
long number = 0;
if(atol(input) < 0){
    printf("went into here\n");
    printf("atoi = %d\n", atoi(input)); 
    number = -1 * atoi(input);  
    printf("number = %d\n", number);    
}else{
    number = atoi(input);
}

But for some reason when my user inputs -2147483648 (and probably other really large decimals), the multiply by -1 doesn't work, and the number remains negative. Any ideas?

tkausl
  • 13,686
  • 2
  • 33
  • 50
Joseph Perez
  • 118
  • 1
  • 11
  • 3
    Because a 32bit signed integer value can not be +2147483648. The two's complement of -2147483648 is -2147483648. – tkausl Sep 14 '16 at 01:42
  • omg im so dumb. This assignment is even supposed to get us familiar with unsigned/signed/binary limits on 32 bits – Joseph Perez Sep 14 '16 at 01:43
  • 1
    If you're compiling for 64 bit on a system when `long` is a 64 bit type (most places aside from Windows), making it `-1L * atoi(input)` would resolve that corner case by forcing promotion to `long`. – ShadowRanger Sep 14 '16 at 01:51
  • unfortunately I'm doing this for a class and on my 32-bit RaspPi so there's that – Joseph Perez Sep 14 '16 at 04:00
  • @JosephPerez there's nothing prevents the Pi from doing 64-bit math – phuclv Sep 14 '16 at 04:04
  • Using a 64-bit data type only moves the "value overflows" case to a larger range of numbers, and does nothing to solve the "no overflow detection/handling" bug. For this reason the suggestion to use a 64-bit data type should be considered an indication of incompetence. – Brendan Sep 14 '16 at 04:40

3 Answers3

1

Unfortunately memory allocated for any standard tipe is limited, so ranges of all all types have quite definite borders. Violated borders lead to computing errors.

To know borders (like min and max possible values) for integer types (not only int, but also char, short, etc.) you can use limits.h. E.g.:

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

int main(void)
{
    printf("INT_MIN = %d\n", INT_MIN);
    printf("INT_MAX = %d\n", INT_MAX);
    printf("LONG_MIN = %ld\n", LONG_MIN);
    printf("LONG_MAX = %ld\n", LONG_MAX);
    printf("LLONG_MIN = %lld\n", LLONG_MIN);
    printf("LLONG_MAX = %lld\n", LLONG_MAX);
    return 0;
}

Note:

1) values of limits depends on compiler and platform (e.g. for my system LONG_MIN is equal to INT_MIN, but perhaps, you will see different values);

2) limits.h is just text file that can be oppend and explored

3) also learn about stdint.h, that provide types with fixed sizes (and allows programs to be portable without "perhaps" in my first note)

4) there are some techniques to detect integer overflow

Community
  • 1
  • 1
VolAnd
  • 6,367
  • 3
  • 25
  • 43
1

For both atoi() and atol(); if the converted value is out of range for the return type (int and long int respectively), then you get undefined behaviour (e.g. "format hard drive").

To avoid undefined behaviour you must ensure that the value in the string is within a certain range before using either atoi() or atol().

Any technique that correctly ensures the value in the string is within a certain range (without using either atoi() or atol()) is also a technique that can be modified slightly and used to detect and handle the INT_MIN case (without using either atoi() or atol()).

Brendan
  • 35,656
  • 2
  • 39
  • 66
0

You are running into the value limit for a signed long integer. You will need to try using another data type.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Hiren
  • 130
  • 1
  • 2
  • 11