why the output of following c program is -10 - c

#include <stdio.h>
int main() {
unsigned int a = -10;
printf("a=%d\n", a);
return 0;
}
The above code is printing -10 for signed int. If the both signed and unsigned are printing the -10 then what is difference between them?

printf doesn't know about the type of the argument that you're giving it. With %d you're telling it that it's a signed int, which is wrong. That's undefined behavior - anything could happen. What will likely happen is that it's just interpreting that memory as signed int anyway, and with the unsigned int a=-10; you set the unsigned int to what will be interpreted as -10 when read as signed int. For further info on what happens with that assignment of a negative number to an unsigned type, check out this answer.

You actually have undefined behavior in that code.
The "%d" format is for plain signed int, and mismatching format specifier and argument leads to UB.
Since printf doesn't have any idea of the real types being passed, it has to rely only on the format specifiers. So what probably happens is that the printf function simply treats the value as a plain signed int and print it as such.

You should use
printf("a=%u\n",a);
to print "a" as an unsigned integer

Related

Why I have to use %u with unsigned int and I can use %i with unsigned char?

I tried to play with data types in C. My first problem was printf() show negative value with unsigned int. I fixed this with %u instead of %i.
But unsigned char still works with %i, how it is possible?
#include <stdio.h>
int main(void) {
unsigned int a;
unsigned char b;
a = -7;
b = -1
printf("a=%u\nb=%i\n", a, b);
return 0;
}
If you see e.g. this printf (and family) reference you will see that the "%i" format do
converts a signed integer into decimal representation [-]dddd.
[Emphasis not mine]
Since you pass an unsigned int you're having mismatched format specifier and value, which leads to undefined behavior.
Furthermore, for variable argument functions (like printf) arguments smaller than int (like for example char, signed or unsigned) are promoted to int. And again, since the resulting value is an int (which is signed) and you use the "%u" format, there is a mismatch between format specifier and argument type.
As it has been stated before, using 'i' as the format specifier is not correct for a variable of type unsigned char.
Whenever you are unsure of what the correct format would be for any particular (integer) type, you can just take a look at inttypes.h, which contains a bunch of macros meant to be used for portable format strings. Depending on the platform you're developing for, the correct format specifiers might differ (uint16_t could be 'u' or 'hu', int32_t could be 'd' or 'ld' for instance).
You could either use this header as a "cheat sheet", or actually write your format strings like this:
printf("a=%"PRIu32"\nb=%"PRIu8"\n", a, b);
Note that for the code to actually be portable, you would of course also need to use uint8_t instead of unsigned char, and uint32_t instead of int.

Why unsigned int stills signed? [duplicate]

This question already has answers here:
C Unsigned int providing a negative value?
(3 answers)
Closed 5 years ago.
I create an unsigned int and unsigned char. Then I assign the -10 value, and the char remains unsigned and gives me a value of 246, but the unsigned int takes the -10 value.
#include <stdio.h>
int main ()
{
unsigned char a;
unsigned int b;
a=-10;
b=-10;
printf("%d\t%d\n", a,b);
}
Compiling and executing I have this:
246 -10
I have no idea why the unsigned int stills signed, and why the char is unsigned.
Reading the book "The C programming language 2nd edition" I can see char can be unsigned by default depending on the machine.
(I'm running NetBSD as a operating system.)
Why the int is signed while I'm declaring as unsigned int, and why the char is taking the value 246?
Is this a compiler or system operating "feature" ?
This is undefined behavior when you pass unsigned integers to %d. Wrong format specifier is UB.
If you assign a negative value to an unsigned variable, it's fine and the value will be taken modulo UINT_MAX + 1 (or UCHAR_MAX + 1), so (-10) % (UCHAR_MAX + 1) = 256 - 10 = 246, and b is 4294967296 - 10 = 4294967286. Unsigned integral overflow is required to wrap-around.
When printf is interpreting these numbers, it finds 246 is suitable for %d, the format specifier for signed int, and 4294967286 is reinterpreted as -10. That's all.
When you assign -10 to an unsigned char variable, the value is reduced modulo UCHAR_MAX + 1, which results in 246 on your platform. Printing an unsigned char value using format %d is fine on most platforms. The value gets implicitly converted to int, which is the correct type for %d format. So, you see that 246 as you should.
When you assign -10 to an unsigned int variable, the value is reduced modulo UINT_MAX + 1, which results in some large value (depends on the range of unsigned int on your platform). Printing such large unsigned int value (greater than INT_MAX) using format %d leads to undefined behavior. The output is meaningless.
%d is the specifier used to print signed int, so it is not strange. Use %u instead.
http://www.cplusplus.com/reference/cstdio/printf/
And when you assign a negative value to an unsigned variable you will get overflow. That's why you get strange values.
printf("%d", a) means that will take the content of variable a and interpret it as a signed int.
Oh, and btw. You are causing undefined behavior which implies that there's really no reason to ask why something happens. Undefined behavior will always be undefined. Avoid it at all costs. Note that the only thing that is undefined is the printf statement. Assigning a value that's out of range to an unsigned variable is a defined behavior. However, the opposite is not true. int a = UINT_MAX will cause undefined behavior.

Printing the hex value stored as a string gives unexpected output

I have in C language hex numbers defined in string:
char chars[] = "\xfb\x54\x9c\xb2\x10\xef\x89\x51\x2f\x0b\xea\xbb\x1d\xaf\xad\xf8";
Then I want to compare the values with another. It is not working and if I print the value like:
printf("%02x\n", chars[0]);
it writes fffffffb. Why is that and how to get fb value exactly?
This is because of the sign extension.
Change
printf("%02x\n", chars[0]);
to
printf("%02x\n", (unsigned char)chars[0]);
The %x format specifier will read 4 bytes on 32bit machine. As you have declared chars as the character array, when fetching the value fb(negative value) will be sign extended as fffffffb, where the MSB of fb is set to all other bits before it.
Refer this for more details sign extension
If you would have declared char chars[] as unsigned char chars[] then the print would have been as expected.
As per the standard mentioning regarding the %x format specifier with fprintf()
o,u,x,X
The unsigned int argument is converted to unsigned octal (o), unsigned
decimal (u), or unsigned hexadecimal notation (x or X) in the style dddd; [...]
So, the expected type of argument to %x is unsigned int.
Now, printf() being a variadic function, only default promotion rule is applied to its arguments. In your code, chars being an array of type char (signedness of which is implementation dependent), in case of
printf("%02x\n", chars[0]);
the value of chars[0] get promoted to an int which is not the expected type for %x. Hence, the output is wrong, as int and unsigned int are not the same type. [Refer ยง6.7.2, C11]. So, without an explicit cast like
printf("%02x\n", (unsigned int)chars[0]);
it invokes undefined behaviour.
FWIW, if you're having a C99 supported compiler, you can make use of the hh length modifier to work around this, like
printf("%02hhx\n", (unsigned char)chars[0]);
It's because of sign extension.
This will work as you expect:
printf("%02x\n", (unsigned char)chars[0]);

Use of unsigned int in different cases? [duplicate]

This question already has answers here:
Unsigned int in C behaves negative
(8 answers)
Closed 8 years ago.
I want to ask what is the difference between these two cases ?
Case1:
unsigned int i;
for(i=10;i>=0;i--)
printf("%d",i);
It will result in an infinite loop!
Case2:
unsigned int a=-5;
printf("%d",a);
It will print -5 on the screen.
Now the reason for case 1 is that i is declared as unsigned int so it can not take negative values,hence will always be greater than 0.
But in case 2, if a cannot take negative values, why -5 is being printed???
What is the difference between these two cases?
The difference is that you are printing a as a signed integer.
printf("%d",a);
so while a may be unsigned, then the %d is asking to print the binary value as a signed value. If you want to print it as a unsigned value, then use
printf("%u",a);
Most compilers will warn you about incompatible use of of parameters to printf -- so you could probably catch this by looking at all the warnings and fix it.
When a -ve value is assigned to an unsigned variable, it can't hold that value and that value is added to UINT_MAX and finally you get a positive value.
Note that using wrong specifier to print a data type invokes undefined behavior.
See C11: 7.21.6 p(6):
If a conversion specification is invalid, the behavior is undefined.282)
unsigned int a=-5;
printf("%u",a); // use %u to print unsigned
will print the value of UINT_MAX - 5.
i is declared unsigned so it can not take negative values
That is correct. Most optimizing compilers will notice that, drop the condition from the loop, and issue a warning.
In case 2, if a can not take negative values, why -5 is being printed?
Because on your platform int and unsigned int have such a representation that assigning -5 to unsigned int and then passing it to printf preserves the representation of -5 in the form that lets printf produce the "correct" result.
This is true on your platform, but other platforms may be different. That is why the standard considers this behavior undefined (i.e. printf could produce any output at all). If you print using the unsigned format specifier, you will see a large positive number.

A strange phenomenon using casting in C

the following code:
int main() {
int small_num = 0x12345678;
int largest_num = 0xFFFFFFFF;
printf("small: without casting to short: 0x%.8x, with casting to short: 0x%.8x\n", small_num>>16, (short)(small_num>>16));
printf("large: without casting to short: 0x%.8x, with casting to short: 0x%.8x\n", largest_num>>16, (short)(largest_num>>16));
return 0;
}
gives me the output (using codepad):
small: without casting to short: 0x00001234, with casting to short: 0x00001234
large: without casting to short: 0xffffffff, with casting to short: 0xffffffff
That's seems extremely strange. Anyone have an idea why it happens this way?
When you are casting to (short) in the printf call, then the compiler will cast it from short back to int, which is the parameter which is passed to printf. Therefore, 1234 will be mapped to 1234, and ffff (which is exactly -1) is mapped to ffffffff. Note that negative integers are expanded from short to long by adding "on bits" on their left.
Short answer
The hexadecimal constant has type unsigned int. When converted to signed int the value becomes -1. Right-shifting a negative value usually leaves the sign-bit unchanged, so -1 >> 16 is still -1. A short int passed to a variadic function gets promoted to signed int which, when interpreted as an unsigned int by the %x conversion specifier, prints out 0xffffffff.
Long answer
However, your code is broken for a number of reasons.
Integer conversion
int largest_num = 0xFFFFFFFF;
The type of the hexadecimal constant is the first of the following types in which its value can be represented: int, unsigned int, long int, unsigned long int, long long int, unsigned long long int.
If int has more than 32 bits, you're fine.
If int has 32 bits or less, The result is implementation-defined (or an implementation-defined signal is raised).
Usually, largest_num will have all bits set and have the value -1.
Shifting a negative value
largest_num>>16
If the value of largest_num is negative, the resulting value is implementation-defined. Usually, the sign bit is left unchanged so that -1 right-shifted is still -1.
Integer promotion
printf ("0x%.8x\n", (short)(largest_num>>16));
When you pass a short int to a variadic function, the value will be promoted to int. A negative value will be preserved when converted to the new type.
However, the "%x" conversion specifier expects an unsigned int argument. Because unsigned int and signed int are not compatible types, the behaviour of the code is undefined. Usually, the bits of the signed int is re-interpreted as an unsigned int, which results in the original value of the hexadecimal constant.
Calling a variadic function
printf(...);
printf() is a variadic function. Variadic functions (typically) use different calling conventions than ordinary functions. Your code invokes undefined behaviour if you don't have a valid declaration of print() in scope.
The usual way to provide a declaration for printf() is to #include <stdio.h>.
Source: n1570 (the last public draft of the current C standard).

Resources