In the following sample code, how did printf knew the size that shall be printed for uint8_t while the mentioned format is only "0x%x" and passd type is uint32_t? how did printf know that in first call it must print 4 bytes and the second call it must only print 1 byte?
uint32_t X = 0xAABBCCDD;
printf("uint32_t 0x%x\n", (uint32_t) X);
printf("uint8_t 0x%x\n", (uint8_t) X);
Output
uint32_t 0xaabbccdd
uint8_t 0xdd
It doesn't know. In both cases you're giving printf an [unsigned] int, due to the default argument promotions. Your code is equivalent to this:1
printf("uint32_t 0x%x\n", (unsigned int)(uint32_t) X);
printf("uint8_t 0x%x\n", (int)(uint8_t) X);
The promotion rule is:
[6.3.1.1] If an
intcan represent all values of the original type [...], the value is converted to anint; otherwise, it is converted to anunsigned int.
The only rule that printf follows at this point is to not print leading zeros.
Note that mapping a signed int to %x is technically undefined behaviour.
ints here.
In
printf("uint8_t 0x%x\n", (uint8_t) X);
uint8_t is definitely a lower-ranking type than int, and so uint8_t will be promoted to int and "%x" will work.
//potentially invokes UB depending on platform
printf("uint32_t 0x%x\n", (uint32_t) X);
is nonportable code. In theory, you don't know what real type uint32_t is and so you should be using the PRIx32 macro from inttypes.h. For consistency/simplicity's sake, you can use PRIx8 for uint8_t too.
#include <inttypes.h>
#include <stdio.h>
int main()
{
uint32_t X = 0xAABBCCDD;
printf("uint8_t 0x%" PRIx8 "\n", (uint8_t) X);
printf("uint32_t 0x%" PRIx32 "\n", (uint32_t) X);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With