55

I am trying to print an uint16_t and uint32_t value, but it is not giving the desired output.

#include <stdio.h>
#include <netinet/in.h>

int main()
{
    uint32_t a = 12, a1;
    uint16_t b = 1, b1;
    a1 = htonl(a);
    printf("%d---------%d", a1);
    b1 = htons(b);
    printf("\n%d-----%d", b, b1);
    return 0;
}

I also used

 printf("%"PRIu32, a);

which is showing an error.

How do I print these values and what will be the desired output?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
xrcwrn
  • 5,339
  • 17
  • 68
  • 129
  • 7
    It would be much more helpful to show us the (exact!) error message rather than just saying that it's "showing error". And rather than just "not giving desired o/p", show us the actual output (and spell out the word "output" rather than writing "o/p"). – Keith Thompson Aug 25 '12 at 08:59
  • 1
    `printf("%d---------%d",a1);` produces undefined behaviour because you have two %d in the format string but only pass one parameter. – Jerry Jeremiah Aug 06 '18 at 05:11
  • 2
    Possible duplicate of [Format specifiers for uint8\_t, uint16\_t, ...?](https://stackoverflow.com/questions/6993132/format-specifiers-for-uint8-t-uint16-t) – phuclv Apr 30 '19 at 03:57

2 Answers2

79

You need to include inttypes.h if you want all those nifty new format specifiers for the intN_t types and their brethren, and that is the correct (ie, portable) way to do it, provided your compiler complies with C99. You shouldn't use the standard ones like %d or %u in case the sizes are different to what you think.

It includes stdint.h and extends it with quite a few other things, such as the macros that can be used for the printf/scanf family of calls. This is covered in section 7.8 of the ISO C99 standard.

For example, the following program:

#include <stdio.h>
#include <inttypes.h>
int main (void) {
    uint32_t a=1234;
    uint16_t b=5678;
    printf("%" PRIu32 "\n",a);
    printf("%" PRIu16 "\n",b);
    return 0;
}

outputs:

1234
5678
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
20

The macros defined in <inttypes.h> are the most correct way to print values of types uint32_t, uint16_t, and so forth -- but they're not the only way.

Personally, I find those macros difficult to remember and awkward to use. (Given the syntax of a printf format string, that's probably unavoidable; I'm not claiming I could have come up with a better system.)

An alternative is to cast the values to a predefined type and use the format for that type.

Types int and unsigned int are guaranteed by the language to be at least 16 bits wide, and therefore to be able to hold any converted value of type int16_t or uint16_t, respectively. Similarly, long and unsigned long are at least 32 bits wide, and long long and unsigned long long are at least 64 bits wide.

For example, I might write your program like this (with a few additional tweaks):

#include <stdio.h>
#include <stdint.h>
#include <netinet/in.h>  

int main(void)
{
    uint32_t a=12, a1;
    uint16_t b=1, b1;
    a1 = htonl(a);
    printf("%lu---------%lu\n", (unsigned long)a, (unsigned long)a1);
    b1 = htons(b);
    printf("%u-----%u\n", (unsigned)b, (unsigned)b1);
    return 0;
}

One advantage of this approach is that it can work even with pre-C99 implementations that don't support <inttypes.h>. Such an implementation most likely wouldn't have <stdint.h> either, but the technique is useful for other integer types.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • 1
    There's one very minor edge case here, if signed int is not two's complement. In that case, it won't correctly hold the most negative two's complement value. VERY minor, I'll admit but something to watch out for if you want maximum portability. – paxdiablo Mar 25 '15 at 01:13
  • 1
    @paxdiablo: The `intN_t` types are required to be two's-complement with no padding bits. If `int` is not two's-complement, then the `intN_t` types probably won't be defined *unless* the implementation supports distinct two's-complement types as well. Good point, but I think it's an even more minor edge case than you suggest. – Keith Thompson Mar 25 '15 at 02:58
  • 1
    No doubt. I suspect you'd have a hard time finding a machine on the planet that sported the new integral types yet still had a ones' complement or sign/magnitude `int` type :-) – paxdiablo Mar 25 '15 at 04:50