I have a function that gets an unsigned long variable as parameter and I want to print it in Hex.
What is the correct way to do it?
Currently, I use printf with "%lx"
void printAddress(unsigned long address) {
printf("%lx\n", address);
}
Should I look for a printf pattern for unsigned long hex? (and not just "long hex" as mentioned above)
Or does printf convert numbers to hex only using the bits? - so I should not care about the sign anyway?
Edit/Clarification
This question was rooted in a confusion: hex is just another way to express bits, which means that signed/unsigned number is just an interpretation. The fact that the type is unsigned long therefore doesn't change the hex digits. Unsigned just tells you how to interpret those same bits in your computer program.
You're doing it right.
From the manual page:
o, u, x, X
The unsigned int argument is converted to unsigned octal (o), unsigned decimal (u), or unsigned hexadecimal (x and X) notation.
So the value for x should always be unsigned. To make it long in size, use:
l
(ell) A following integer conversion corresponds to a long int or unsigned long int argument [...]
So %lx is unsigned long. An address (pointer value), however, should be printed with %p and cast to void *.
I think the following format specifier should work
give it a try
printf("%#lx\n",address);
Related
I am not understanding what is major difference between %p,%u,%x,%d, except that %x shows hexadecimal,%u is used for unsigned integer and that %d is for any integer. I am very much confused after I took a integer variable and printed its address and its value (positive integer) separately, then irrespective of whatever format specifier I use, it was correctly printing the output (except of the difference in hexadecimal and decimal number system). So what is a major difference?
And if there is not much difference then which format specifiers are preferable for printing what type of variables?
Another doubt is that: Whether pointer of all multiplicity (I mean int *p; int **p; int ***p; etc.) occupy the same size (which is the size needed to store a valid address in the machine)? If not, then what is the size of these pointers?
Thanks for your help.
The %u, %x, %d, and %p format specifiers are used as follows:
%u: expects an unsigned int as a parameter and prints it in decimal format.
%x: expects an unsigned int as a parameter and prints it in hexadecimal format.
%d: expects an int as a parameter and prints it in decimal format.
%p: expects a void * as a parameter and prints it in an implementation defined way (typically as a hexadecimal number)
Additionally, %u, %x, %d can be prefixed with a length modifier:
l: denotes a long int or unsigned long int
ll: denotes a long long int or unsigned long long int
h: denotes a short int or unsigned short int
hh: denotes a signed char or unsigned char
Regarding pointer sizes, int *, int **, int ***, etc. are not required to be the same size, although on most implementations they will be.
With format specifiers, you tell the computer how to interpret the given variable/data.
A quick demo:
#include <stdio.h>
int main(void)
{
int x = -5;
printf("x value as int: [%d]\n", x);
printf("x value as unsigned int: [%u]\n", x);
printf("x value as hexadecimal: [%x]\n", x);
printf("x value as pointer: [%p]\n", x);
return 0;
}
Output:
x value as int: [-5]
x value as unsigned int: [4294967291]
x value as hexadecimal: [fffffffb]
x value as pointer: [0xfffffffb]
It's the same value given every time, i.e. x = -5.
We see the exact representation when given the right format specifier (the first case).
In second case we see a very big number. The answer to "Why" is a bit long to explain here, but you should look up how negative integers are represented in 2's complement system.
In the third case we see the hexadecimal representation of the number 4294967291. Hexadecimal numbers are usually shown with 0x at the beginning but %x doesn't do that.
The last one just shows how would the variable x seem if it were an address in the memory, again in hexadecimal format of course.
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]);
Given,
unsigned short y = 0xFFFF;
When I print
printf("%x", y);
I get : 0xFFFF;
But when I print
printf("%x", (signed short)y);
I get : 0xFFFFFFFF
Whole program below:
#include <stdio.h>
int main() {
unsigned short y = 0xFFFF;
unsigned short z = 0x7FFF;
printf("%x %x\n", y,z);
printf("%x %x", (signed short)y, (signed short)z);
return 0;
}
Sign extension happens when we typecast lower to higher byte data type, but here we are typecasting short to signed short.
In both cases sizeof((signed short)y) or sizeof((signed short)z) prints 2 bytes. Short remains of 2 bytes, if sign bit is zero as in case of 0x7fff.
Any help is very much appreciated!
Output of the first printf is as expected. The second printf produces undefined behavior.
In C language when you pass a a value smaller than int as a variadic argument, that value is always implicitly converted to type int. It is not possible to physically pass a short or char variadic argument. That implicit conversion to int is where your "sign extension" takes place.
For this reason, your printf("%x", y); is equivalent to printf("%x", (int) y);. The value that is passed to printf is 0xFFFF of type int. Technically, %x format requires an unsigned int argument, but a non-negative int value is also OK (unless I'm missing some technicality). The output is 0xFFFF.
Conversion to int happens in the second case as well. I.e. your printf("%x", (signed short) y); is equivalent to printf("%x", (int) (signed short) y);. The conversion of 0xFFFF to (signed short) is implementation-defined, because 0xFFFF is apparently out of range of signed short on your platform. But most likely it produces a negative value (-1). When converted to int it produces the same negative value of type int (again, -1 represented as 0xFFFFFFFF for a 32-bit int). The further behavior is undefined, since you are passing a negative int value for format specifier %x, which requires unsigned int argument. It is illegal to use %x with negative int values.
In other words, formally your second printf prints unpredictable garbage. But practically the above explains where that 0xFFFFFFFF came from.
Let's break it down and into smaller pieces:
Given,
unsigned short y = 0xFFFF;
Assuming two-bytes unsigned short maximum value is 2^16-1, that is indeed 0xFFFF.
When I print
printf("%x", y);
Due to default argument promotion (as printf() is variadic function) value of y is implicitly promoted to type int. With %x format-specified it's treated as unsigned int. Assuming common two-complement's representation and four-bytes int type, that means that as most-significant bit is set to zero, the bit patterns of int and unsigned int are simply the same.
But when I print
printf("%x", (signed short)y);
What you have done is cast to signed type, that cannot represent value of 0xFFFF. Such conversion as standard stays is implementation-defined, so you can get whatever result. After implicit conversion to int apparently you have bit-patern of 32-ones, that are represented as 0xFFFFFFFF.
#include <stdio.h>
#include <string.h>
int main(void) {
char buf[256] = {};
unsigned long i=13835058055298940928;
snprintf(buf, 1024, "%lx", i); /* Line 7 */
printf("%s\n",buf);
return 0;
}
In line 7, if I use %lux, and then snprintf doesn't do any conversion. It just prints 0x13835058055298940928x, whereas if I use just %lx, it prints an expected hexadecimal conversion.
How do I represent unsigned long in hexadecimal?
A format of "%lux" is treated as "%lu" (unsigned long, decimal) followed by a letter x.
The "%x" format requires an argument of unsigned type; there's no (direct) mechanism to print signed integers in hexadecimal format.
The format for printing an unsigned long value in hexadecimal is "%lx". (x is hexadecimal, d is signed decimal, u is unsigned decimal; any of them may be qualified with l for long.)
Note that the value 13835058055298940928 requires at least a 64-bit unsigned type to store it without overflow. The type unsigned long is at least 32 bits; it's 64 bits on some systems, but by no means all. If you want your code to be portable, you should use type unsigned long long rather than unsigned long. The format for printing an unsigned long long value in hexadecimal is "%llx".
For clarity, I usually precede hexadecimal output with 0x, so it's obvious to the reader that it's a hexadecimal number:
printf("0x%llx\n", some_unsigned_long_long_value);
(You can achieve the same result with %#llx, but I find it easier to write out 0x than to remember the meaning of the # flag.)
I have an unsigned integer but when i print it out using %d there is sometimes a negative value there?
Printing %d will read the integer as a signed decimal number, regardless of its defined type.
To print unsigned numbers, use %u.
This happens because of C's way to handle variable arguments. The compiler just pulls values from the stack (typed as void* and pointing to the call stack) and printf has to figure out what the data contains from the format string you give it to.
This is why you need to supply the format string - C has no way of RTTI or a 'base class' (Object in Java, for example) to get a generic or predefined toString from.
This should work:
unsigned int a;
printf("%u\n", a);
Explanation: On most architectures, signed integers are represented in two's complement. In this system, positive numbers less than 2**(N-1) (where N = sizeof(int)) are represented the same way regardless whether you are using an int or a unsigned int. However, if the number in your unsigned int is larger than 2**(N-1), it represents a negative signed number under two's complement -- which is what printf gave you when you passed it "%d".
%d means printf will interpret the value as an int(which is signed). use %u if it is an unsigned int.