1

why compiler is not generating error for this

gone through some answers but didn't get what exactly is the reason. some helps us with some simple answer to understand this

#include <stdio.h>
int main()
{
    unsigned int a=-1;
    printf("Result :%d",a);
    return 0;
}

result :-1

dbush
  • 205,898
  • 23
  • 218
  • 273
Ganesh
  • 27
  • 3
  • 1
    Because -1 is the same as 0xffffff in the case of an unsigned int with two's bit compliment. There's no reason to throw an error; however there will be a warning. Assign unsigned int a to 0xffffffff and print the result. – Irelia Jul 19 '19 at 13:27
  • 1
    [C11 H.2.2](http://port70.net/~nsz/c/c11/n1570.html#H.2.2): *"... C's unsigned integer types are ''modulo'' in the LIA-1* [language independent arithmetic] *sense in that overflows or out-of-bounds results silently wrap. ..."* – pmg Jul 19 '19 at 13:30
  • okay, so where exactly will be using the concept of signed and unsigned integers in the real time applications – Ganesh Jul 19 '19 at 13:33
  • If you use GCC and the `-Wconversion` warning, you get a warning such as `aaz59.c:4:20: error: unsigned conversion from ‘int’ to ‘unsigned int’ changes value from ‘-1’ to ‘4294967295’ [-Werror=sign-conversion]`. The warning is not part of either `-Wall` or `-Wextra` (the compiler doesn't complain about the conversion when both those are specified but `-Wconversion` is not separately and explicitly specified. It can be hard work avoiding all such warnings, which is one reason it must be explicitly enabled. – Jonathan Leffler Jul 19 '19 at 13:53

2 Answers2

2

This is an error

    unsigned int a=-1;
    printf("Result :%d",a);

You cannot use "%d" to print an unsigned value, you must use "%u".

pmg
  • 106,608
  • 13
  • 126
  • 198
  • "%d" is it for both unsigned and signed and when we have tried with"%u" the output is different, thats some random number ..? – Ganesh Jul 19 '19 at 13:40
  • 2
    It is not a random number. It will be 0xFFFFFFFF on systems where integers are 4 bytes long. – jmq Jul 19 '19 at 13:45
  • @Ganesh: the conversion specification `%d` is for a signed `int` value — it is not for printing the full range of `unsigned int`. – Jonathan Leffler Jul 19 '19 at 14:33
-1

@Ganesh,

The compiler will not produce an error in this case.

C language gives you extreme power, but you need to be careful. Using the "unsigned" keyword tells the compiler how to treat MSB (most significant bit). To be more precise, when you assign a variable of type "int" to a memory location, it will reserve some space in memory (depending on the platform). For simplicity, let's say that int reserves 8 bits of memory, hence: 1 2 3 4 5 6 7 8. Each of the numbers represent a bit (single memory location which can hold either 0 or 1) in a byte (series of 8 bits). When you declare: signed integer and you type in:

signed int a = -1;

The compiler will do this: 1 0 0 0 _ 0 0 0 1 (_ is there just to make series of numbers easier to read).

This will not be read as some extremely large number. This will be read as "negative 1", because the most significant bit (first bit reading from left to right) will be read as a sign. That means that signed int value uses only 7 bits (in this example) for storing value of a number, whereas one bit will be used to store the sign (0 means that number is positive, 1 means that number is negative).

What does the "unsigned" keyword do?

When you tell compiler:

unsigned int a = 1;

It completely changes how the number will be read. Remember that memory place: 1 2 3 4 5 6 7 8? Well, the bit at the position 1 will no longer be able to store the sign of a number. Meaning that all eight bits will be used for storing the value of a number.

In the binary case: 1 0 0 0 _ 0 0 0 1 as a signed int would be read as -1, but as an unsigned value it will be something large (you can see the exact number using bin to dec converter online, but that is not the point).

So, what is the problem with your code? First one is:

(1) unsigned int a = -1;

And the second one is:

(2) printf ("%d", a);

So, let's talk why doesn't the code crash with the first statement?

World of C is based on assembler instructions (doesn't matter what they are, for now) and it is totally binary.

C does not care about numbers, really. They are just there to help programmer write a readable programme.

When you specify -1, doesn't matter what type of data it is, the memory: 1 2 3 4 5 6 7 8 will be filled like:

1 2 3 4 .. 5 6 7 8
1 0 0 0 .. 0 0 0 1

End of story. Compiler acts in this order:

(1) keyword (int, float, ...): reserve space for the variable (2) value (-1): convert to binary word(s) (3) end of story.

When compiler converts the literal (number like: -1, 60, 2.63262, whatever), it will always, in case of a "-" sign assign the MSB as: 1 (once again: MSB is x 2 3 4 5 6 7 8, the x position). Using compiler instructions like -Wall on gcc:

gcc -Wall test.c -o test.o

will give you all the warnings: "I expected to get this, but I got this". Warnings can be your best friends, but I generally find them more evil than beneficiary.

You can even say:

int a = 5.125;

This is a float number, but the compiler will not argue (maybe warning would arise, but no error).

I think this clarifies a bit why the:

unsigned int a = -1;

can pass the compiler.

The second thing is "printf". That is probably the worst way to check what value your variable holds, as you can see that you assigned -1 to unsigned variable, and then read it out as -1.

That's just the thing: 1 0 0 0 _ 0 0 0 1 to the computer does not mean anything. It's just series of information (HIGH / LOW value of voltage), but computer is just stupid for everything else. Programmes are the ones that make computers understand what these information mean.

When you say: printf("%d", a), using %d spaceholder, you are saying: okay, fetch me the information stored in variable "a". The computer gets: 1 0 0 0 _ 0 0 0 1. As, I've told, the computer is ignorant to everything else. It cannot understand what these series of voltages (represented as numbers) mean.

That's where %d comes in. It tells the computer: okay, read the binary value where the 1st bit is a value for the sign, and convert remaining (7 bits) to a decimal number, and print it out on terminal (that black box you will see the number printed / if you are using Windows, it is called command prompt).

So, %d is a spaceholder that tells that the fetched number will be interpreted with a value for the sign. That is the reason why:

unsigned int a = -1;
>> -1

prints out -1.

But, if you were to use, as pmg has mentioned, %u spaceholder, then it will tell compiler to treat: 1 0 0 0 _ 0 0 0 1 message as a number where there isn't any bit that will represent the sign of a number, hence, you will get something like 6316136236136 printed out (okay, not that large, but you probably get the point).

To conclude this, rather long elaborate,

(1) in C language be careful with variable types and be consistent; (2) pay extremely close attention to the printf spaceholders, as they will interpret the value differently, for example:

float a = 5.125;
printf("%f", a);
>> 5.1250
printf("%d", a);
>> god knows what number you'll get (I just got: 1508905080)

I hope these information guide you to the right track. You can comment down and I'll get to you as soon as I can.

Amaterastis
  • 477
  • 3
  • 12