C Language

A closer look at signed and unsigned integers in C.

what is difference between signed and unsigned integers?

Many times I have found that people make mistakes when they are using signed and unsigned integers. Sometimes the basic mistake can create hidden issues and waist you’re a lot of time in searching the bugs. I know, everybody aware from the signed and unsigned integer but still they are making mistakes that’s why in this article I am explaining some important points and questions regarding the signed and unsigned integer.

An integer has no fractional part, in c language integer generally represented by short, int and long. The size of the long must be at least 32 bits, and the size of the int and short must be at least 16 bits but size of the short no longer than int.

We can arrange short, int and long in ascending order in following way:

sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long) (only C99)

I am not interested here to explain data type so I am coming on points with basic viral questions.

Size of the integer depends on what?

The C standard is explained that the minimum size of the integer should be 16 bits. Some programing language is explained that the size of the integer is implementation dependent but portable programs shouldn’t depend on it.

Primarily size of integer depends on the type of the compiler which has written by compiler writer for the underlying processor. You can see compilers merrily changing the size of integer according to convenience and underlying architectures.So it is my recommendation use the C99 integer data types ( uin8_t, uin16_t, uin32_t ..) in place of standard int.



Are integers signed or unsigned?

In standard C language, integer data type is by default signed. So if you create an integer variable, it can store both positive and negative value.

What is a difference between unsigned int and signed int in C?

The signed and unsigned integer type has the same storage (according to the standard at least 16 bits) and alignment but still, there is a lot of difference them, in bellows lines, I am describing some difference between the signed and unsigned integer.

  • A signed integer can store the positive and negative value both but beside it unsigned integer can only store the positive value.
  • The range of nonnegative values of a signed integer type is a sub-range of the corresponding unsigned integer type.
    For example,

Assuming size of the integer is 2 bytes.

signed int                                            -32768 to +32767

unsigned int                                         0 to 65535

  • When computing the unsigned integer, it never gets overflow because if the computation result is greater than the largest value of the unsigned integer type, it is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.

For example,

Computational Result  % (Largest value of the unsigned integer+1)

  • The overflow of signed integer type is undefined.
  • If Data is signed type negative value, the right shifting operation of Data is implementation dependent but for the unsigned type, it would be Data/ 2pos.
  • If Data is signed type negative value, the left shifting operation of Data show the undefined behavior but for the unsigned type, it would be Data x 2pos.




How do I convert a signed integer to an unsigned integer?

It is a basic question, generally asked by people on the internet but really it is very confusing and sometimes kills your mind. In C language compiler perform automatic (implicit ) casting but some compiler gives the warning so every time we need to cast explicitly using the parenthesis to convert one type into the other type.

Let’s take an example,

int iData = 17;
unsigned int uiData = (unsigned int)iData;

Here I am not interested to know to how to convert signed and unsigned integer vice versa but I am interested to know what happens if I am converting a signed integer to unsigned integer or unsigned integer to signed integer.
For the better understanding, I am taking few examples and seeing what happen if converting signed and unsigned to each other.

Converting a positive signed number to the unsigned integer:

Output: 27

Explanation:  As per the C99 standard, when a value of integer type is converted to another type (except _Bool (C99))  and if the value can be represented by the new type then it will be unchanged.

Converting a negative signed integer to an unsigned integer:

If you have a variable of type signed int, and it contains a negative value such as -6 then how do you convert this to an unsigned data type and what exactly happens if you perform a cast?

The answer to this question is that nothing happens because according to C99 standard if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

Output: 0xfffffffa

In the above example, I am assuming the size of the integer is a 4 bytes (32 bit). Let us assume that the compiler represents signed negative integers number in 2’s complement notation (not mentioned by the C standard) when casting the negative integer number than no bits will be changed the only compiler treat the stored bits as the unsigned integer.

So if we analyze the above example, the binary representation of -6 will be 0xFFFFFFFA (4294967290).This value comes under the range of unsigned int so after the casting of this value there is no specific effects happened on the bits.

Note: Need to remember, it is not the fact that casting -6 to an unsigned type will be 0xFFFFFFFA. Whether it does or not depends entirely on how the compiler chooses to represent negative numbers.

Converting an unsigned integer to signed integer type:

As per the C99 standard if the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.

Let’s take an example to understand the above statement.

In the below example, I am assuming that size of the integer is 4byte (32bit). I am creating an unsigned integer variable whose value is 19891992, the assigned value is in the range of signed integer variable. So if we converting the unsigned integer value to the signed integer variable there will be no effect reflect.

 Output: 19891992

In another example, I am assigning the max value to the unsigned integer variable, when converting unsigned integer to the signed integer then the value is the out of the range of signed integer.The result value will be implementation dependent.

Output: 4294967295
4294967295



Who is more efficient signed int or unsigned int?

Basically In my view unsigned int is far better than signed int, the behavior of unsigned int is well documented by the c standard but in some scenarios behavior of signed int is not defined.

In below I am discussing few points in favor of unsigned int.

  • The overflow of unsigned int is fully defined by the c standard community but not defined for the signed int.
  • When we will shift the signed negative value then its results depends on the implementation.
  • The range of unsigned int is larger than the range of the signed int.
  • The modulus operation is almost defined for the unsigned int.
  • Generally in the embedded system port and register deal with unsigned int because the value of the register and port treated as unsigned entities.
  • Using the unsigned int we can reduce some conditional statement.

For example,
if you have created a function which contains the look-up table, the arguments of the function should be unsigned integer type because of array index always a positive number.

Generally, when we create a lookup table we need to check the index of the lookup table because if it goes beyond the boundary then your code can crash. The function which contains the lookup table if the argument of that function is signed integer type then you have to put one more condition to check the index of lookup table because index should be greater or equal to zero.

Function with the signed integer as arguments:

In above code snippet, I have to put two conditions because the argument of the function is signed integer type.

Function with the unsigned integer as arguments:

In above example, the function contains unsigned integer as arguments then there is no need to put two conditions because the value of unsigned int never goes less than zero.



When need to use signed int?

I am mentioning here some scenario where we need to use the signed int in place of the unsigned int.

  • When dealing with library function that has required int as arguments.
  • When performing the arithmetic operation then taking signed integer is beneficial.
  • When in a program you need to assign the negative integer value.

What happens if mixed signed and unsigned int?

If we mixed signed and unsigned int in the program then it can create issues because as per the c standard if we perform the arithmetic operation on signed and unsigned number then the resultant value can be implementation dependent or undefined in some scenarios.

In C99, integer promotion is clearly defined that If an int can represent all values of the original type, the value is converted to an int, otherwise, it is converted to an unsigned int. All other types are unchanged by the integer promotions.

Note: My advice is that never mixed the signed and unsigned and always enable the warning option in your IDE.

See the below program and think the output of,

If you are familiar with integer promotion then, of course, you know the answer either you need to read the integer promotion. So it is my recommendation when you performed an arithmetic operation where the operands are signed and unsigned then carefully perform the operation either you will get the undefined result.

In below I am mentioning few points, you need to take care these points before performing the arithmetic operation.

  • If the value of the signed integer is negative then you have to take care before performing shifting and arithmetic operation.
  • If the value of the unsigned integer is greater than the maximum value that is represented by the signed integer.
  • The integer promotion rules can create a problem if you are not careful.

Your opinion matters

Although here I have tried to discuss a lot of points regarding the signed and unsigned integers I would like to know your opinion of the issues which you have faced related to signed and unsigned integers. So please don’t forget to write a comment in the comment box.



4 Comments

  1. Mark Odell

    Very simple. Never use signed types unless you expect or require negative values. For example, for loop iteration often runs from zero to some positive limit. Why would you ever declare the loop iteration variable an int? Unsigned or size_t tells the reader more clearly your intent.

    • Amlendra

      Yes agreed, but I saw many people used signed int with array index and in loops.In my previous project, I saw that some my colleagues used signed int without any requirements in math engine and compare signed and unsigned int, the compiler throws the warning but they just avoid it that is the reason I have written an article on signed and unsigned int.

  2. San

    >>”The range of unsigned int is larger than the range of the signed int”
    I’m not agree. The range is equal for int and uint.

    >> printf(“%u\n”,iData);
    Also if you want to print int variable, you should use “%i” or “%d”.
    When you use “%u” the compiler casts the value back to unsigned int.

  3. San

    “The range is equal for int and uint.” – I mean: the count of the possible values (that can be stored in the int or uint variable) is equal.

Leave a Reply

Theme by Anders Norén