Search code examples
cprintfunsigned-integer

Print unsigned short int in hex and decimal C


I've been trying to print unsigned short int values in C with no luck. As far as I know, it's a 16 bit value, so I've tried several different methods to print this 2 bytes together, but I've only been able to print it correctly when doing it byte by byte.

Note that I want to print this 16 bits in both a decimal and hexadecimal format, for example 00 01 as 1, another example would be: 00 ff as 255.

I have this struct:

struct arphdr {
   unsigned short int ar_hrd;
   unsigned short int ar_pro;
   unsigned char ar_hln;
   unsigned char ar_pln;
   unsigned short int ar_op;
   // I'm commenting the following part because I won't need it now
   // for the explanation
   /* unsigned char __ar_sha[ETH_ALEN];
   unsigned char __ar_sip[4];
   unsigned char __ar_tha[ETH_ALEN];
   unsigned char __ar_tip[4]; */ 
};

And this function:

void print_ARP_msg(struct arphdr arp_hdr) {
   // I need to print the arp_hdr.ar_hrd in both decimal and hex.
   printf("Format HW: %04x\n", arp_hdr.ar_hrd);
   printf("Format Proto: %04x\n", arp_hdr.ar_pro);
   printf("HW Len: %x\n", arp_hdr.ar_hln);
   printf("Proto Len: %x\n", arp_hdr.ar_pln);
   printf("Command: %04x\n", arp_hdr.ar_op);
}

The print_ARP_msg function returns me this:

Format HW: 0100

Format Proto: 0008

HW Len: 6

Proto Len: 4

Command: 0100

The hex values of the struct are "00 01 08 00 06 04 00 01", so I don't know why it's returning me 0100 in the arp_hdr.ar_hrd value.

Also, I made a function which prints the struct in hex, to make sure that I'm doing it right, and I was able to check, that all the fields where correctly assigned.

PS: before sending this question, I realized that it's printing the correct Hex values but disordered. Could it be related to the little/big endian "difference"?


Solution

  • Could it be related to the little/big endian "difference"?

    Yes. If you're dealing with packets that have arrived over a network - and you're printing fields of an ARP packet, so that's exactly what you're doing - you may have to convert from the byte order of the fields as they are when sent over the network to the byte order on the machine on which you're running.

    For example:

    printf("Format HW: %04x\n", ntohs(arp_hdr.ar_hrd));
    

    In that particular case, you can get away without the ntohs() call on a big-endian machine (SPARC, System/3x0, z/Architecture, PowerPC/Power ISA running AIX, PowerPC/Power ISA running Mac OS X, possibly PowerPC/Power ISA running Linux, etc.), but you can't get away without it on a little-endian machine (anything with an x86 processor, including x86-64 processors, probably most ARM, etc.).

    You can use it on both types of processor.