Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Printf() printing character as 32 bit

Tags:

c

printf

I'm running a quick test to make sure I have my pointer arithmetic down:

main.c

#include <stdio.h>
#include <stdlib.h>

#define ADDRESS    0xC0DCA11501LL
#define LENGTH     5


void print_address( char *, char );

/* Main program */
int main( int argc, char *argv[] )
{
    char nums[ LENGTH ];

    /* LSB first */
    for( int i = 0; i < LENGTH; i++ )
    {
        nums[ i ] = ( ADDRESS >> ( 8 * i ) ) & 0xFF;
    }

    print_address( nums, LENGTH );

    system("PAUSE");

    return 0;
}

void print_address( char *data, char len )
{
     char *data_ptr = data;

     while( len-- )
     {
            printf( "%X\n", *data_ptr++ );
     }
}

What I expect is the bytes of ADDRESS to be printed out LSB first in hex format. But the last 3 bytes appear to be printed with 32-bit lengths:

1
15
FFFFFFA1
FFFFFFDC
FFFFFFC0
Press any key to continue . . .

Is this due to my bit-shifting arithmetic, something compiler-specific, some printf() behavior?

(I'm using MinGW GCC v6.3.0 on Windows 10 to compile.)

like image 670
calcium3000 Avatar asked Mar 16 '18 18:03

calcium3000


2 Answers

I believe that your char is a being used as a signed value and that you are seeing the FFFFs because 0xA1 is greater than 0x80 and is therefore showing up signed. Try using unsigned char pointer (and for the nums array and data in your function prototype) and the problem should go away.

like image 140
Michael Dorgan Avatar answered Oct 28 '22 03:10

Michael Dorgan


Type char seems to be signed in your environment, such that A1 as an 8 bit value actually represents a negative number. Note then that the varargs of printf are promoted to int type, and a negative number is filled up with leading 1-bits. In other words, signed A1 when promoted to 32 bit integer will give FFFFFFA1. That's why.

Use unsigned char instead:

void print_address( unsigned char *, char );

/* Main program */
int main( int argc, char *argv[] )
{
    unsigned char nums[ LENGTH ];

    /* LSB first */
    for( int i = 0; i < LENGTH; i++ )
    {
        nums[ i ] = ( ADDRESS >> ( 8 * i ) ) & 0xFF;
    }

    print_address( nums, LENGTH );

    system("PAUSE");

    return 0;
}

void print_address( unsigned char *data, char len )
{
    unsigned char *data_ptr = data;

    while( len-- )
    {
        printf( "%X\n", *data_ptr++ );
    }
}
like image 29
Stephan Lechner Avatar answered Oct 28 '22 02:10

Stephan Lechner