To test if an string converts to a unsigned

Use strtoul() to convert to a unsigned long. Yet since that function rolls over negative text to positive integers, use strtol() first.

bool valid_unsigned(const char *s, unsigned *uval) {
  char *endptr;
  errno = 0;
  int base = 0; // Use 10 here if only decimal text acceptable.
  long lvalue = strtol(s, &endptr, base);
  if (s == endptr) {
    *uval = 0;
    return false;  // No conversion
  }
  if (lvalue < 0) {
    errno = ERANGE;  // Perhaps calling code would like to test this.
    *uval = 0;
    return false; // Negative
  }
  if ((unsigned long) lvalue <= UINT_MAX && errno == 0) {
    *uval = (unsigned) lvalue;
    return true; // Success
  }

  #if UINT_MAX > LONG_MAX
    // Still could be a value in the LONG_MAX...UINT_MAX range.
    errno = 0;
    unsigned long uvalue = strtoul(s, &endptr, base);
    if (uvalue <= UINT_MAX && errno == 0) {
      *uval = (unsigned) uvalue;
      return true;  // Success
    }
  #endif
  errno = ERANGE;
  *uval = UINT_MAX;
  return false;  // Too big.
} 

To do: Test trailing text.

Answer from chux on Stack Overflow
🌐
TutorialsPoint
tutorialspoint.com › cprogramming › c_data_types.htm
C - Data Types
The type of a function specifies the type of the function's return value. We will see the basic types in the following section, where as other types will be covered in the upcoming chapters. The following table provides the details of standard integer types with their storage sizes and value ranges −
Top answer
1 of 3
2

To test if an string converts to a unsigned

Use strtoul() to convert to a unsigned long. Yet since that function rolls over negative text to positive integers, use strtol() first.

bool valid_unsigned(const char *s, unsigned *uval) {
  char *endptr;
  errno = 0;
  int base = 0; // Use 10 here if only decimal text acceptable.
  long lvalue = strtol(s, &endptr, base);
  if (s == endptr) {
    *uval = 0;
    return false;  // No conversion
  }
  if (lvalue < 0) {
    errno = ERANGE;  // Perhaps calling code would like to test this.
    *uval = 0;
    return false; // Negative
  }
  if ((unsigned long) lvalue <= UINT_MAX && errno == 0) {
    *uval = (unsigned) lvalue;
    return true; // Success
  }

  #if UINT_MAX > LONG_MAX
    // Still could be a value in the LONG_MAX...UINT_MAX range.
    errno = 0;
    unsigned long uvalue = strtoul(s, &endptr, base);
    if (uvalue <= UINT_MAX && errno == 0) {
      *uval = (unsigned) uvalue;
      return true;  // Success
    }
  #endif
  errno = ERANGE;
  *uval = UINT_MAX;
  return false;  // Too big.
} 

To do: Test trailing text.

2 of 3
1

If you are using the function strtoul for converting the string input to an integer, then you don't need to determine yourself whether the input is larger than ULONG_MAX. The function strtoul will report this, by setting the value of errno accordingly. However, depending on the platform, an unsigned long may be able to represent more numbers than an unsigned int. Therefore, after the function strtoul reports that the input range is ok, you should additionally verify that the number is not larger than UINT_MAX.

Another problem with using the function strtoul is that it will accept negative numbers as valid. We must therefore check ourselves whether the first non-whitespace character is a minus sign.

Here is an example program which uses a function get_unsigned_int_from_user which will continue prompting the user for input, until the input is valid and in the range of an unsigned int:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>

unsigned int get_unsigned_int_from_user( const char *prompt )
{
    for (;;) //loop forever until user enters a valid number
    {
        char buffer[1024], *p, *q;
        unsigned long ul;

        //prompt user for input
        fputs( prompt, stdout );

        //get one line of input from input stream
        if ( fgets( buffer, sizeof buffer, stdin ) == NULL )
        {
            fprintf( stderr, "unrecoverable error reading from input\n" );
            exit( EXIT_FAILURE );
        }

        //make sure that entire line was read in (i.e. that
        //the buffer was not too small)
        if ( strchr( buffer, '\n' ) == NULL && !feof( stdin ) )
        {
            int c;

            printf( "line input was too long!\n" );

            //discard remainder of line
            do
            {
                c = getchar();

                if ( c == EOF )
                {
                    fprintf( stderr, "unrecoverable error reading from input\n" );
                    exit( EXIT_FAILURE );
                }

            } while ( c != '\n' );

            continue;
        }

        //make "p" point to first non-whitespace character
        for ( p = buffer; isspace( (unsigned char)*p ); p++ )
            ;

        //since the function "strtoul" accepts negative
        //input as valid input, which we don't want, we must
        //first check ourselves whether the input starts
        //with a minus sign
        if ( *p == '-' )
        {
            printf( "number must not be negative!\n" );
            continue;
        }

        //attempt to convert string to number
        errno = 0;
        ul = strtoul( p, &q, 10 );
        if ( q == p )
        {
            printf( "error converting string to number\n" );
            continue;
        }

        //make sure that number is representable as an "unsigned int"
        if ( errno == ERANGE || ul > UINT_MAX )
        {
            printf( "number out of range error\n" );
            continue;
        }

        //make sure that remainder of line contains only whitespace,
        //so that input such as "6sdfh4q" gets rejected
        for ( ; *q != '\0'; q++ )
        {
            if ( !isspace( (unsigned char)*q ) )
            {
                printf( "unexpected input encountered!\n" );

                //cannot use `continue` here, because that would go to
                //the next iteration of the innermost loop, but we
                //want to go to the next iteration of the outer loop
                goto continue_outer_loop;
            }
        }

        return ul;

    continue_outer_loop:
        continue;
    }
}

int main( void )
{
    unsigned int num;

    num = get_unsigned_int_from_user( "Please enter a number: " );

    printf( "Input is valid, you entered: %u\n", num );
}

This program has the following behavior:

Please enter a number: -1  
number must not be negative!
Please enter a number: -5000000000
number must not be negative!
Please enter a number: 5000000000
number out of range error
Please enter a number: 4000000000
Input is valid, you entered: 4000000000

The program behaves this way because UINT_MAX has the value 4294967295 on most common platforms.

The function get_unsigned_int_from_user is a modified version of my function get_int_from_user from this answer of mine. See that answer for further information on how that function works.

Discussions

Binary basics - why in C is the range of "int" -32768 to 32767 when 2^32 (4 bytes) is 4.294.967.296 different values?
Why do you think the range is -32768 to 32767? What happens when you print either the sizeof an int, or INT_MAX? More on reddit.com
🌐 r/learnprogramming
14
0
November 2, 2022
c - What does "-1" represent in the value range for unsigned int and signed int? - Stack Overflow
I am learning C and have a dumb question regarding the "-1" in the value range for unsigned int and signed int. I can't seem to find an explanation for it anywhere. The paragraph below explains the More on stackoverflow.com
🌐 stackoverflow.com
Range of values in C Int and Long 32 - 64 bits - Stack Overflow
I'm confused with range of values of Int variable in C. I know that a 32bits unsigned int have a range of: 0 to 65,535. So long has 0 to 4,294,967,295 This is fine in 32bits machine. But now in 6... More on stackoverflow.com
🌐 stackoverflow.com
What is the use of unsigned char?
There are 3 character types: signed char unsigned char char (yes, this is indeed a distinct type, not "alias", but for practical purposes it is the same as one of the above two, implementation specified) sizeof for these is defined to be 1. Using sizeof char is always redundant, though it can be used like a comment, making code more clear. On any platform you are likely to ever work on, char is 8 bits, and synonym to "byte". Therefore, int8_t is probably signed char and uint8_t is unsigned char typedefs. More on reddit.com
🌐 r/cpp_questions
39
9
April 20, 2023
🌐
Quora
quora.com › What-is-the-range-of-an-unsigned-int
What is the range of an unsigned int? - Quora
C/C++ guarantees only that sizeof(unsigned int) >= sizeof(unsigned short) and that CHAR_BIT >= 8; the minimum range required by the C standard is 0 to 65,535 (i.e., at least 16 bits).

To test if an string converts to a unsigned

Use strtoul() to convert to a unsigned long. Yet since that function rolls over negative text to positive integers, use strtol() first.

bool valid_unsigned(const char *s, unsigned *uval) {
  char *endptr;
  errno = 0;
  int base = 0; // Use 10 here if only decimal text acceptable.
  long lvalue = strtol(s, &endptr, base);
  if (s == endptr) {
    *uval = 0;
    return false;  // No conversion
  }
  if (lvalue < 0) {
    errno = ERANGE;  // Perhaps calling code would like to test this.
    *uval = 0;
    return false; // Negative
  }
  if ((unsigned long) lvalue <= UINT_MAX && errno == 0) {
    *uval = (unsigned) lvalue;
    return true; // Success
  }

  #if UINT_MAX > LONG_MAX
    // Still could be a value in the LONG_MAX...UINT_MAX range.
    errno = 0;
    unsigned long uvalue = strtoul(s, &endptr, base);
    if (uvalue <= UINT_MAX && errno == 0) {
      *uval = (unsigned) uvalue;
      return true;  // Success
    }
  #endif
  errno = ERANGE;
  *uval = UINT_MAX;
  return false;  // Too big.
} 

To do: Test trailing text.

Answer from chux on Stack Overflow
🌐
Wikipedia
en.wikipedia.org › wiki › C_data_types
C data types - Wikipedia
1 week ago - SCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX(C99) – maximum possible value of signed integer types: signed char, signed short, signed int, signed long, signed long long · UCHAR_MAX, USHRT_MAX, UINT_MAX, ULONG_MAX, ULLONG_MAX(C99) – maximum possible value of unsigned integer types: unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long
🌐
Microsoft Learn
learn.microsoft.com › en-us › cpp › cpp › data-type-ranges
Data Type Ranges | Microsoft Learn
The Microsoft C++ 32-bit and 64-bit compilers recognize the types in the table later in this article. - int (unsigned int) - __int8 (unsigned __int8) - __int16 (unsigned __int16) - __int32 (unsigned __int32) - __int64 (unsigned __int64) - short (unsigned short) - long (unsigned long) - long long (unsigned long long) If its name begins with two underscores (__), the data type is nonstandard. The ranges ...
Find elsewhere
Top answer
1 of 5
49

Consider the values you can achieve with 2 bits:

00 : 0
01 : 1
10 : 2
11 : 3

There are 4 of them, 2 to the power of 2.
But the highest value is not 4, it is 3.
The highest value is 2 to the power of 2 minus 1. I.e. in your representation

2^2-1
or 22-1

Add a bit and you get twice the number, by adding

100 : 4
101 : 5
110 : 6
111 : 7

Total number 8, but highest number 7.

So the "-1" is because always the first of the total of 2n is used for 0,
the 2nd is used for 1, the 3rd is used for 2.
In the end (2n)th one is not available for 2n, it is already used for 2n-1.

2 of 5
26

n bits can represent 2n different values. (The first bit can have two values * the second bit can have two values * the third bit can have two values * ...)

For example, 3 bits can form 23 = 8 different bit patterns, and thus up to 8 different values.

000
001
010
011
100
101
110
111

If each bit pattern represents an integer, then an n-bit integer can represent 2n different integers. For example,

  • It could represent the integers from 0 to 2n-1 inclusively
    (because (2n-1) - (0) + 1 = 2n different values).

    For example,

      000   0
      001   1
      010   2
      011   3
      100   4
      101   5
      110   6
      111   7
    
  • It could represent the integers from -(2n-1) to 2n-1-1 inclusively
    (because (2n-1-1) - (-(2n-1)) + 1 = 2n different values).

    For example,

      100  -4
      101  -3
      110  -2
      111  -1
      000   0
      001   1
      010   2
      011   3
    

You could assign any meaning to these values, but the previously stated ranges are the ones understood by twos'-complement machines for unsigned integers and signed integers respectively.[1]


  1. On a ones'-complement machine, there are two ways of writing zero (0000...00002 and 1000...00002), so the range is only -(2n-1-1) to 2n-1-1. I think all modern machines are twos'-complement machines, though.
🌐
EDUCBA
educba.com › home › software development › software development tutorials › c programming tutorial › unsigned int in c
Unsigned Int in C | Working of Unsigned Int in C with Examples
April 15, 2023 - We know that the data type “int” ... int can contain storage size either 2 or 4 bytes where values ranging from [0 to 65,535] or [0 to 4,294,967,295]. The format specifier used for an unsigned int data type in C is “ %u ...
Address   Unit no. 202, Jay Antariksh Bldg, Makwana Road, Marol, Andheri (East),, 400059, Mumbai
🌐
Cprogramming
cboard.cprogramming.com › c-programming › 155762-data-type-range.html
Data Type Range
April 8, 2013 - I have seen that unsigned int ranges from 0 to 4,294,967,295. I cannot print this to the user without a warning though. I'm just trying to understand the limits of variables, so this is just for my reference. Here is the code: ... #include <stdio.h> int main(){ unsigned int a = 4294967295; ...
🌐
GeeksforGeeks
geeksforgeeks.org › c language › data-types-in-c
Data Types in C - GeeksforGeeks
We use int keyword to declare the integer variable: Size: typically 4 bytes, Range: -2,147,483,648 to 2,147,483,647. Format specifier: %d. Format specifiers are the symbols that are used for printing and scanning values of given data types.
Published   3 weeks ago
🌐
PrepBytes
prepbytes.com › home › c programming › unsigned int in c
Unsigned Int in C
January 17, 2024 - Like if an unsigned int inc is represented using 32 bits then it can hold the value from 0 to 4294967295. We can calculate the range of values that an unsigned int in c can hold by using the following formula.
🌐
GNU
gnu.org › software › libc › manual › html_node › Range-of-Type.html
Range of Type (The GNU C Library)
Suppose you need to store an integer value which can range from zero to one million. Which is the smallest type you can use? There is no general rule; it depends on the C compiler and target machine. You can use the ‘MIN’ and ‘MAX’ macros in limits.h to determine which type will work.
🌐
W3Schools
w3schools.com › c › c_data_types_extended.php
C More Data Types (Extended Types)
unsigned means the type can only store non-negative values (0 and up). *Note: The size of these types can differ between systems (for example, 2 or 4 bytes, or 4 or 8 bytes), depending on whether the computer is older or newer, 32-bit or 64-bit, ...
🌐
Sanfoundry
sanfoundry.com › c-program-print-range
Range of Data Types in C | Data Types in C - Sanfoundry
November 16, 2022 - The output range for the fundamental data types of int, char, and short is shown below. range of int -2147483648 to 2147483647 range of unsigned int 0 to -1 range of char -128 to 127 range of unsigned char 0 to 255 range of short -32768 to 32767 ...
🌐
BYJUS
byjus.com › gate › size-of-data-types-in-c
Size of Data Types in C
February 16, 2024 - Thus, the range for such characters is from 0 to 255. These character data types are capable of storing the ASCII characters or the numbers that are equivalent to the ASCII characters.
🌐
GeeksforGeeks
geeksforgeeks.org › c language › ranges-of-data-types-in-c
Ranges of Data Types in C - GeeksforGeeks
January 24, 2026 - The ranges of data types in C define ... example, int typically ranges from -2,147,483,648 to 2,147,483,647 for signed, and 0 to 4,294,967,295 for unsigned on a 32-bit system....
🌐
IME USP
ime.usp.br › ~pf › algorithms › chapters › int-and-char.html
What is a signed int? an unsigned int? a char?
Overflows may go unnoticed because they are not treated as errors and the exact result of each operation is automatically reduced modulo UINT_MAX + 1. For example: int i, j, x; i = 2147483000; j = 2147483000; x = i + j; // overflow // x == -1296 · The assignment of an unsigned int to an int ...
🌐
TutorialKart
tutorialkart.com › c-programming › c-unsigned-int-data-type
C unsigned int Data Type - Storage Size, Examples, Min and Max Values
February 20, 2025 - ... #include <stdio.h> int main() ... int only holds non-negative values, its range starts from 0 and extends to a higher maximum value than a signed int of the same size....