0

I have following function:

void hexDump(char *buf, size_t size) {
for(int i = 0; i < size; i++) {
    if(i % 4 == 0) {
        printf("\n");
    }

    printf("%02x ", buf[i]);
}

The first two lines always output fine, but the next lines break:

24 00 00 00 
00 0a 04 04 
ffffffe8 ffffffd9 22 63 
00 00 00 00 
02 00 0a 00 
...

Real content of buf obtained by gdb:

0x7fffffffd320: 0x24    0x00    0x00    0x00    0x00    0x0a    0x04    0x04
0x7fffffffd328: 0xe8    0xd9    0x22    0x63    0x00    0x00    0x00    0x00
0x7fffffffd330: 0x02    0x00    0x0a    0x00    0x00    0x00    0x00    0x00

How can I fix it?

2 Answers2

2

Four things leads to this problem:

  1. It's implementation-defined if char is signed or unsigned.
  2. Default argument promotion leads to char values being promoted to int.
  3. When signed integer values are promoted, it's sign-extended to keep negative values negative.
  4. Negative values are usually stored using two's complement, which sets the top bit.

All this leads to a value like 0xf0 could be considered negative, and will be promoted to 0xfffffff0 as an int.

To print only the byte use the hh prefix:

printf("%02hhx ", buf[i]);

Or make sure that the data is unsigned:

void hexDump(unsigned char *buf, size_t size) { ... }

Alternatively, instead if unsigned char use uint8_t.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

Here are 3 fixups

void hexDump( unsigned char *buf, size_t size ) {
    for( size_t i = 0; i < size; i++ )
        printf( "%02x%c", buf[ i ], "   \n"[ i % 4 ] );
}

1 - buf should be treated like hex. Hexadecimal is unsigned

2 - size_t i Don't compare an int to a size_t type

3 - indexing into a 4 byte string (3 x SP and 1 x LF) eliminates the if()

You could even go on to add the snazzy address column on the left:

#include <stdio.h>
#include <string.h>

void hexDump( unsigned char *buf, size_t size ) {
    for( size_t i = 0; i < size; i++ ) {
        if( i % 4 == 0 )
            printf( "%04X ", i );
        printf( "%02x%c", buf[ i ], "   \n"[ i % 4 ] );
    }
}

int main() {
    char *str = "The quick brown fox jumps over the lazy dogs";
    hexDump( (unsigned char*) str, strlen( str ) + 1 );
    return 0;
}

Output

0000 54 68 65 20
0004 71 75 69 63
0008 6b 20 62 72
000C 6f 77 6e 20
0010 66 6f 78 20
0014 6a 75 6d 70
0018 73 20 6f 76
001C 65 72 20 74
0020 68 65 20 6c
0024 61 7a 79 20
0028 64 6f 67 73
002C 00

Or, the ACTUAL memory address with 8 / line. (Notice now 7xSP + 1xLF)

void hexDump( unsigned char *buf, size_t size ) {
    for( size_t i = 0; i < size; i++ ) {
        if( i % 8 == 0 )
            printf( "%p ", buf + i );
        printf( "%02x%c", buf[ i ], "       \n"[ i % 8 ] );
    }
}
/* Output */
00422B10 54 68 65 20 71 75 69 63
00422B18 6b 20 62 72 6f 77 6e 20
00422B20 66 6f 78 20 6a 75 6d 70
00422B28 73 20 6f 76 65 72 20 74
00422B30 68 65 20 6c 61 7a 79 20
00422B38 64 6f 67 73 00
Fe2O3
  • 6,077
  • 2
  • 4
  • 20