How atol() works ?? - 32 bit & 31 bit - Signed and Unsigned explanation

First, let's see the format specifiers of int and long and how to remember it easily.

Format SpecifierType - Range
%d (INT_MIN)Integer or Signed Integer (4 bytes)
-2,147,483,648 to +2,147,483,647 
%uUnsinged Integer (4 bytes)
0 to 4,294,967,295 
%ld (LONG_MIN)Long or Signed Long (4 bytes)
-2,147,483,648 to +2,147,483,647 
%luUnsigned Long (4 bytes)
0 to 4,294,967,295
We'll play with bits and bytes for some time.

Unsigned integer is an integer that can't be negative and thus it has the higher range of positive values. 
Signed integer is an integer that can be negative and thus it has the lower positive range in exchange for more negative values. 

bits  value
0000    0
0001     1
0010     2
0011      3
0100     4
0101     5
0110     6
0111      7
1000   -8
1001    -7
1010    -6
1011     -5
1100    -4
1101     -3
1110     -2
1111      -1

Signed Decimal - 2147483647 
Binary Number - 111 1111 1111 1111 1111 1111 1111 1111 (31 bits)
Binary Signed 2's Compliment - 0111 1111 1111 1111 1111 1111 1111 1111 (32 bits)
Hex Number - 7FFF FFFF

Signed Decimal - -2147483648
Binary Number - 1000 0000 0000 0000 0000 0000 0000 0000 (32 bits)
Hex Signed 2's Compliment - 80000000
Hex Number - 8000 0000

Unsigned Decimal - 4294967295
Binary Number - 1111 1111 1111 1111 1111 1111 1111 1111 (32 bits)
Binary Signed 2's Compliment -  1111 1111 1111 1111 1111 1111 1111 1111 (32 bits)
Hex Number - FFFFFFFF

With this, It's obvious that singed datatypes can always be fully consuming 32 bits as the MSB will be set for negative numbers and unsigned also consumes 32 bits especially for the higher positive numbers.

                             

Do we have any drawbacks with atol() function?

#include <stdio.h>

int main()
{
    unsigned long big_ulong = 4294967295;
    long big_long = 4294967295;
    int big_int = 4294967295;
    char str[15] = "4294967295";
    unsigned int small_uint = 0;
    unsigned long small_ulong = 0;

    printf("big_ulong 4294967295\n\t d[%d] in u [%u] in ld [%ld] in lu[%lu]\n", 
           big_ulong, big_ulong, big_ulong, big_ulong);
    printf("big_long 4294967295\n\t d [%d] in u [%u] in ld [%ld] in lu[%lu]\n", 
           big_long, big_long, big_long, big_long);
    printf("big_int 4294967295\n\t d[%d] in u [%u] in ld [%ld] in lu[%lu]\n", 
           big_int, big_int, big_int, big_int);
    printf("str 4294967295\n\t [%s] small_ulong[%lu]\n", str, small_ulong);
    small_ulong = atol(str);
    small_uint = atol(str);
    printf("small_ulong 4294967295\n\t d[%d] in u [%u] in ld [%ld] in lu[%lu]\n", 
           small_ulong, small_ulong, small_ulong, small_ulong);
    printf("small_uint 4294967295\n\t d[%d] in u [%u] in ld [%ld] in lu[%lu]\n", 
           small_uint, small_uint, small_uint, small_uint);
    return 0;
}

Output:
1
2
3
4
5
6
7
8
9
10
11
12
big_ulong 4294967295
	 d[-1] in u [4294967295] in ld [-1] in lu[4294967295]
big_long 4294967295
	 d [-1] in u [4294967295] in ld [-1] in lu[4294967295]
big_int 4294967295
	 d[-1] in u [4294967295] in ld [-1] in lu[4294967295]
str 4294967295
	 [4294967295] small_ulong[0]
small_ulong 4294967295
	 d[2147483647] in u [2147483647] in ld [2147483647] in lu[2147483647]
small_uint 4294967295
	 d[2147483647] in u [2147483647] in ld [2147483647] in lu[2147483647]




As per the above example, atol is recommended only for signed long, or in other words, it is only for 32 bits datatype.


Reference: GeeksforGeeks


Comments