How to print 5 byte integer values? - c

I've just started reading C and have a question about a macro.
How can I print a 5 byte integer value (that happens to be defined in a macro)?
For example:
#define MAX 0xdeadbeaf12
int main(){
printf(" 0x %2x \n", MAX);
}
This code prints adbeaf12 but not deadbeaf12.
How do I get all the bytes printed?

I prefer to make my assumptions about the size of a variable explicit. The following uses standard (though often unused) macros to define a 64-bit constant and print such a quantity as a hex value.
#include <stdio.h>
// Pull in UINT64_C and PRIx64 macros
#include <inttypes.h>
// Make this a 64-bit literal value
#define MAX UINT64_C(0xdeadbeaf12)
int main()
{
// Use PRIx64 which inserts the correct printf specifier for
// a hex format of a 64-bit value
printf(" 0x%" PRIx64 " \n", MAX);
}

#define MAX 0xdeadbeaf12LL
Will tell the compiler to use the longest available integer type (which will then be cast to an appropriate type wherever MAX is used).
On most platforms, the numeric literal suffix LL will correspond to signed long long, this is 64bit (8 bytes) on a 32 bit system. C's excellent typing system and compiler warnings will take care of the rest for you.
Your printf then needs to use the ll modifier:
printf(" 0x %2llx \n", MAX);

Related

Sizeof with different specificators [duplicate]

This question already has answers here:
Using %f to print an integer variable
(6 answers)
Closed 3 years ago.
I want to know why sizeof doesn't work with different types of format specifiers.
I know that sizeof is usually used with the %zu format specifier, but I want to know for my own knowledge what happens behind and why it prints nan when I use it with %f or a long number when used with %lf
int a = 0;
long long d = 1000000000000;
int s = a + d;
printf("%d\n", sizeof(a + d)); // prints normal size of expression
printf("%lf\n", sizeof(s)); // prints big number
printf("%f", sizeof(d)); // prints nan
sizeof evaluates to a value of type size_t. The proper specifier for size_t in C99 is %zu. You can use %u on systems where size_t and unsigned int are the same type or at least have the same size and representation. On 64-bit systems, size_t values have 64 bits and therefore are larger than 32-bit ints. On 64-bit linux and OS/X, this type is defined as unsigned long and on 64-bit Windows as unsigned long long, hence using %lu or %llu on these systems is fine too.
Passing a size_t for an incompatible conversion specification has undefined behavior:
the program could crash (and it probably will if you use %s)
the program could display the expected value (as it might for %d)
the program could produce weird output such as nan for %f or something else...
The reason for this is integers and floating point values are passed in different ways to printf and they have a different representation. Passing an integer where printf expects a double will let printf retrieve the floating point value from registers or memory locations that have random contents. In your case, the floating point register just happens to contain a nan value, but it might contain a different value elsewhere in the program or at a later time, nothing can be expected, the behavior is undefined.
Some legacy systems do not support %zu, notably C runtimes by Microsoft. On these systems, you can use %u or %lu and use a cast to convert the size_t to an unsigned or an unsigned long:
int a = 0;
long long d = 1000000000000;
int s = a + d;
printf("%u\n", (unsigned)sizeof(a + d)); // should print 8
printf("%lu\n", (unsigned long)sizeof(s)); // should print 4
printf("%llu\n", (unsigned long long)sizeof(d)); // prints 4 or 8 depending on the system
I want to know for my own knowledge what happens behind and why it prints nan when I use it with %f or a long number when used with %lf
Several reasons.
First of all, printf doesn't know the types of the additional arguments you actually pass to it. It's relying on the format string to tell it the number and types of additional arguments to expect. If you pass a size_t as an additional argument, but tell printf to expect a float, then printf will interpret the bit pattern of the additional argument as a float, not a size_t. Integer and floating point types have radically different representations, so you'll get values you don't expect (including NaN).
Secondly, different types have different sizes. If you pass a 16-bit short as an argument, but tell printf to expect a 64-bit double with %f, then printf is going to look at the extra bytes immediately following that argument. It's not guaranteed that size_t and double have the same sizes, so printf may either be ignoring part of the actual value, or using bytes from memory that isn't part of the value.
Finally, it depends on how arguments are being passed. Some architectures use registers to pass arguments (at least for the first few arguments) rather than the stack, and different registers are used for floats vs. integers, so if you pass an integer and tell it to expect a double with %f, printf may look in the wrong place altogether and print something completely random.
printf is not smart. It relies on you to use the correct conversion specifier for the type of the argument you want to pass.

C sprintf breaks with byte parameters (Keil compiler)

I have code running in 2 projects/platforms. It works in one, not the other. Code is like this:
uint8_t val = 1;
uint8_t buff[16];
sprintf(buff, "%u", val);
The expected output is "1" (gcc) but on one compiler (Keil) it returns "511", which in hex is 0x1FF. Looks like its not promoting the byte to int with this compiler. This is confirmed because it works ok if I do this:
sprintf(buff, "%u", (int)val);
My question is this: why does one compiler do what I consider the 'right thing', and one does not? Is it my incorrect expectations/assumptions, a compiler setting, or something else?
For maximum portability, you can use these macros from inttypes.h: (there are others)
PRId8, PRIx8, PRIu8
PRId16, PRIx16, PRIu16
PRId32, PRIx32, PRIu32
Normally (as I expected):
#define PRIu8 "u"
But for the Keil compiler in this case:
#define PRIu8 "bu"
e.g.,
printf("0x%"PRIx8" %"PRIu16"\n", byteValue, wordValue);
That's pretty cumbersome though. I suggest more friendly compilers.
It's amazing what you don't know about this stuff even after doing it for decades.
Your assumption may be correct, or incorrect. It depends on the compiler implementation. All modern (or should say smart) compiler will do that like you mentioned. But Keil, as of ver. 9.02, you need to specify correct variable length for printf.
This is Keil C's way handling all kinds of printf functions.
You need to specify exactly how long it is. All regular are for 16-bit (unsigned) integer including %d, %x, and %u. Use modifier 'b' for 8-bit and 'l' for 32-bit. If you gave wrong length, you would get wrong number. Even worse, the rest of the variables are all wrong.
For example, to use 8-bit 'char', you use '%bd' (%bu, and %bx), and %ld, %lu, and %lx for 32-bit 'long'.
char c = 0xab;
printf("My char number is correctly displayed as '0x%02bx'\n", c);
Also note, likewise, to get numeric data from sscanf, it's same. The following example is to get a 32-bit long variable using sscanf:
long var;
char *mynum = "12345678";
sscanf(mynum, "%ld", &var);
Variable var contains number 12345678 after sscanf.
Hereunder shows the length for variables used in printf family for Keil.
%bd, %bx, %bu - should be used for 8-bit variables
%d, %x, %u - should be used for 16-bit variables, and
%ld, %lx, %lu - should be used for 32-bit variables

C printf of an integer with %lu produces large number

I know that is bad practice to print an integer with %lu which is a unsigned long. In a project i was working on i got a large number when trying to print 11 with %lu in the snprint format.(old code) I am using gcc 4.9.3.
This code below i thought would produce the wrong number since snprintf is told to read more than the 4 bytes occupied. Its doesnt though. Works perfectly. It reads everything correctly. Either it does not go past the 4 bytes in to the unknown or the extra 4 bytes in the long are fully of zeros when it gets promoted to long from int.
I am wondering out of curiosity is when does printf print the wrong number? What conditions does it need produce a wrong big number? There has to be garbage in the upper 4 bytes but it seems like it does not set that garbage for me.
I read the answers here but the code worked for me. I know its a different compiler.
Printing int type with %lu - C+XINU
#include<inttypes.h>
#include<stdio.h>
int main(void){
uint32_t number1 = 11;
char sentence[40];
snprintf(sentence,40,"Small number :%lu , Big number:%lu \n",number1,285212672);
printf(sentence);
}
On OP's machine, uint32_t, unsigned long and int appear to be the same size #R Sahu. OP's code is not portable and may produce incorrect output on another machine.
when does printf print the wrong number?
Use the matching printf() specifier for truly portable code. Using mis-matched specifiers may print the wrong number.
The output string may be well over 40 characters. Better to use a generous or right-sized buffer.
#include <inttypes.h>
#include <stdio.h>
int main(void){
uint32_t number1 = 11;
// char sentence[40];
char sentence[80];
snprintf(sentence, sizeof sentence,
"Small number :%" PRIu32 " , Big number:%d \n",
number1, 285212672);
// printf(sentence); // Best not to print a string using the printf() format parameter
fputs(sentence, stdout);
}

Displaying an integer to hex in C

I have this part of code in C class:
int i;
for (i=0;i<val;i++)
mdl_print ("%u ", rec->payload[i]);
mdl_print ("\n");
Variable rec->payload is uint8_t type. I would print it in hexadecimal notation.
How can I do? Thanks.
Quick and easy:
print("%x", (int)(rec->payload[i]));
To display in the format 0x05 then use:
print("0x%02x", ...)
instead.
If mdl_print() works like the standard C function printf(), try something like the following:
printf( "%02x", (int) rec->payload[i] );
The basic printf formatting code for writing in hexadecimal is %x. "02" means to pad the number with '0' until it's two characters wide, which is how you'd normally print an int8.
Many custom output functions follow the format of printf in this way, since it's very familiar to C programmers. You can read more about printf on its man page: http://linux.die.net/man/3/printf
Use "%x", so:
mdl_print ("%x ", rec->payload[i]);
This will give you a hex number that is the "length necessary". If you want a fixed length, use "%02x" for two digits padded with zeros.
Note that providing a uint8_t or int where an unsigned int is expected in printf is undefined behaviour, as stated by section 7.21.6.1p9 of n1570.pdf: "If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined." According to 7.21.6.1p8, %x tells printf to expect an unsigned int. Make sure you explicitly cast your uint8_t to (unsigned int), or use the PRIx8 macro found in <stdint.h>.
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
int main(void) {
uint8_t foo = 42;
/* These two printfs are equivalent: */
printf("Hex for %02u: %02x\n", (unsigned int) foo, (unsigned int) foo);
printf("Hex for %02" PRIu8 ": %02" PRIx8 "\n", foo, foo);
return 0;
}
First your title is so wrong... Casting integer to hex in C casting implies a type change, hex is a number system not a type. You're "displaying an integer in hex" not "casting". If you don't understand the difference please ask for clarification.
As far as the displaying goes, it depends what you want the result to look like. One short cut that I typically use is:
mdl_print("%#x ", rec->payload[i]);
Which displays values as:
0xA6
The caveat on this syntax is that it doesn't work with 0, you don't get 0x0 just 0. So an alternative would be:
mdl_print("0x%x ", rec->payload[i]);
Which will display the value as 0xA6 or 0x0 or whatever it maybe. Of course if you don't want the 0x part you can always just do:
mdl_print("%x ", rec->payload[i]);
Your max value (in hex) with a unsigned 8-bit number is 0xFF so if you want them all to display the same "width" you can use the size specifier too:
mdl_print("%02x ", rec->payload[i]); // or mdl_print("0x%02x, rec->payload[i]);
// or whatever you picked

C printf integer type U32

I have the hex value 0x5a800000000b and I'm trying to get a printf statement in C to print it to the console.
So far (because I'm useless in C) I'm able to get the 'b' to print, using the syntax:
printf("Hex value%x\n", value);
The value is stored in an integer type U32, but after trying all different combinations of %llx, %lx, I just keep getting compiler warnings.
I'm guessing that I'm getting the printf syntax wrong, but I can't seem to find the right % option, can someone help me out?
Thanks
It's not a problem with the printf.
The problem is that a 32 bits variable cannot hold the value 0x5a800000000b. 32 bits can hold only 8 hex digits: 0x0000000b. Hence the b on output.
To store such a large value, you should use a 64 bits variable.
long long value = 0x5a800000000bLL
Note also the double L at the end. It tells the compiler that the constant is also a long long.
Then you can use %llx in the printf format string.
There are some pre-defined macro for these types:
#include <inttypes.h>
int64_t PRId64. PRIi64
int32_t PRId32, PRIi32
int16_t PRId16, PRIi16
int8_t PRId8, PRIi8
For example:
printf("%"PRId32"\n", my32Int);
The value 0x5a800000000b is more that 32 bits, so you have to use a long.
long value = 0x5a800000000bl;
printf("Hex value%lx\n", value);
Note that hex constant should end in l,.

Resources