1

I am using the following to print out numbers from an array in hex:

char buff[1000];

// Populate array....

int i;
for(i = 0; i < 1000; ++i)
{
    printf("[%d] %02x\n", i,buff[i]);
}

but I sometimes print weird values:

byte[280] 00     
byte[281] 00     
byte[282] 0a     
byte[283] fffffff4         // Why is this a different length?
byte[284] 4e      
byte[285] 66      
byte[286] 0a   

Why does this print 'fffffff4'?

4
  • 1
    please show // Populate array.... Commented Feb 2, 2018 at 10:04
  • 1
    One safe play, use char buff[1000] = {0}; to avoid using any un-init-ed value. Commented Feb 2, 2018 at 10:05
  • yes, you need to show the code where the bug is. Commented Feb 2, 2018 at 10:06
  • You appear to be targeting a system where plain char is a signed type (and int is 32 bits). Commented Feb 2, 2018 at 11:19

2 Answers 2

13

Use %02hhx as the format string.

From CppReference, %02x accepts unsigned int. When you pass the arguments to printf(), which is a variadic function, buff[i] is automatically converted to int. Then the format specifier %02x makes printf() interprets the value as int, so potential negative values like (char)-1 get interpreted and printed as (int)-1, which is the cause of what you observed.

It can also be inferred that your platform has signed char type, and a 32-bit int type.

The length modifier hh will tell printf() to interpret whatever supplied as char type, so %hhx is the correct format specifier for unsigned char.

Alternatively, you can cast the data to unsigned char before printing. Like

printf("[%d] %02x\n", i, (unsigned char)buff[i]);

This can also prevent negative values from showing up as too long, as int can (almost) always contain unsigned char value.


See the following example:

#include <stdio.h>

int main(){
    signed char a = +1, b = -1;
    printf("%02x %02x %02hhx %02hhx\n", a, b, a, b);
    return 0;
}

The output of the above program is:

01 ffffffff 01 ff
Sign up to request clarification or add additional context in comments.

3 Comments

"%02x accepts unsigned int, which causes your buff[i] to be promoted to int" This is somewhat misleading. Promotion happens because of default argument promotions on variable argument functions. Format string conversion specifiers have nothing to do with it.
@user694733 How can that sentence be improved, in your opinion? Thanks in advance.
I'd like to see distinction between promotion and interpretation. Promotion happens automatically to int before printf is entered, and interpretation to unsigned int of happens inside printf because of %x.
5

Your platform apparantly has signed char. On platforms where char is unsigned the output would be f4.

When calling a variadic function any integer argument smaller than int gets promoted to int.

A char value of f4 (-12 as a signed char) has the sign bit set, so when converted to int becomes fffffff4 (still -12 but now as a signed int) in your case.

%x02 causes printf to treat the argument as an unsigned int and will print it using at least 2 hexadecimal digits. The output doesn't fit in 2 digits, so as many as are required are used.

Hence the output fffffff4.

To fix it, either declare your array unsigned char buff[1000]; or cast the argument:

    printf("[%d] %02x\n", i, (unsigned char)buff[i]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.