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
Are these range of values for a 16-bit machine's integers correct?
long is is required by the language to be at least 32 bits. If the CPU doesn’t support that directly then it must be emulated - bitwise operations, addition, subtraction and multiplication are not too hard to figure out but efficient division is rather tricky! More on reddit.com
🌐 r/C_Programming
23
14
November 6, 2024
🌐
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
6 days 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
🌐
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
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.
🌐
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
🌐
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; ...
🌐
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.
🌐
RapidTables
rapidtables.com › prog › cref › data_types.html
C Data Types - C Programming - RapidTables.com
Data types: void, char, int, float, double, short, long, enum, pointer, array, structure/struct, static, union, extern, ...
🌐
Reddit
reddit.com › r/c_programming › are these range of values for a 16-bit machine's integers correct?
r/C_Programming on Reddit: Are these range of values for a 16-bit machine's integers correct?
November 6, 2024 -

These are the values for 16-bit machine that I got from the C Programming: A Modern Approach, 2nd Edition book by K. N. King.

  • short int: -32,768 to 32,767

  • unsigned short int: 0 to 65,535

  • int: -32,768 to 32,767

  • unsigned int: 0 to 65,535

  • long int: -2,147,483,648 to 2,147,483,647

  • unsigned long int: 0 to 4,294,967,295

Shouldn't a 16-bit machine's unsigned long int range be 0-65,535? Since 1111 1111 1111 1111 is 65,535 I think that the range int he book is wrong. Or am I wrong?

I'm really confused, specially since the range for a 32-bit machine unsigned long int is 0-4,294,967,295 (which is the max value for a 32 bit) and 0-18,446,744,073,709,551,615 the max value for 64 bits. But the book's long int and unsigned long int for a 16-bit machine are the same values for the ones of a 32-bit machine. Way larger than 65,535.

I'm still pretty new at C, so sorry if I'm making a really beginner mistake or I'm not being able to express myself that well.

Thanks.

🌐
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.
🌐
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, ...
🌐
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....