Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to print unsigned char as 2-digit hex value in C?

Tags:

c

keil

I am trying to printout an unsigned char value as a 2-Digit hex value, but always getting the result as 4-Digit hex values, not sure what's wrong with my code.

// unsigned char declaration
unsigned char status = 0x00;
// printing out the value 
printf("status = (0x%02X)\n\r", (status |= 0xC0));

I am expecting a 2 digit hex result as 0xC0, but I always get 0xC0FF.

As well, when I tried to print the same variable (status) as an unsigned char with the %bu format identifier I got the output as 255.

How do you get just the two hex characters as output?

like image 867
Asad Waheed Avatar asked Sep 10 '12 02:09

Asad Waheed


People also ask

How to print the hex value of a char in C?

Using %x format specifier in printf, we can print the hexadecimal values.

How to print value in hex?

Printing the number in Hexadecimal format To print integer number in Hexadecimal format, "%x" or "%X" is used as format specifier in printf() statement. "%x" prints the value in Hexadecimal format with alphabets in lowercase (a-f). "%X" prints the value in Hexadecimal format with alphabets in uppercase (A-F).

Can you print unsigned char?

unsigned char ch = 212 ; And your printf will work. Even with ch changed to unsigned char , the behavior of the code is not defined by the C standard. This is because the unsigned char is promoted to an int (in normal C implementations), so an int is passed to printf for the specifier %u .

How to assign a hex value in C?

In C programming language, we can use hexadecimal literals in any expressions; we can assign hexadecimal numbers to the variables. To use hexadecimal literals, we use 0X or 0x as a prefix with the number. For example 0x10 is a hexadecimal number, which is equivalent to 16 in the decimal number system.


3 Answers

As far as I know, the Keil C compiler doesn't fully conform to the C standard. If so, it's likely that it doesn't quite follow the standard promotion rules for things like passing char values to variadic functions; on an 8-bit CPU, there are performance advantages in not automatically expanding 8-bit values to 16 bits or more.

As a workaround, you can explicitly truncate the high-order bits before passing the argument to printf. Try this:

#include <stdio.h>

int main(void) {
    unsigned char status = 0x00;
    status |= 0xC0;

    printf("status = 0x%02X\n", (unsigned int)(status & 0xFF));
    return 0;
}

Doing a bitwise "and" with 0xFF clears all but the bottom 8 bits; casting to unsigned int shouldn't be necessary, but it guarantees that the argument is actually of the type expected by printf with a "%02X" format.

You should also consult your implementation's documentation regarding any non-standard behavior for type promotions and printf.

like image 137
Keith Thompson Avatar answered Sep 18 '22 20:09

Keith Thompson


you are sending a char to a format string which expects an int. The printf function is grabbing another byte off the stack to fill it out. Try

 printf("%02X",(int)(status|0xC0));
like image 41
AShelly Avatar answered Sep 16 '22 20:09

AShelly


Looking at all the answers, I think probably we are missing another way of doing this.

const unsigned char chararr[]="abceXYZ";
for (int i=0; i< 7; ++i) {
    printf("%#04X %d %c\n", chararr[i], chararr[i], chararr[i]);
}
0X61 97 a
0X62 98 b
0X63 99 c
0X65 101 e
0X58 88 X
0X59 89 Y
0X5A 90 Z

If you use %#04x small x then the output will b 0x small x prefix. The # pound sign tells the function to print the 0x. 04 to instruct how many digits to output, if input is '0x0a' it will print this,without 04 it will print '0xa'.

In my computer, Dell workstation, the output is as expected by the question. Unless

unsigned char status = 0x00;
printf("status = (0x%02X)\n\r", (status |= 0xC0));
// output
//status = (0xC0)
// is exactly expected by the original question. 

Better illustrated by examples:

 37    printf("status = (%#02x)\n", (status |= 0xC0));
 38    printf("status = (%#04x)\n", (status |= 0xC0));
 39    printf("status = (%#04x)\n", 0x0f);
 40    printf("status = (%#02x)\n", 0x0f);
status = (0xc0)
status = (0xc0)
status = (0x0f)
status = (0xf)
like image 35
Kemin Zhou Avatar answered Sep 20 '22 20:09

Kemin Zhou