The reason why this is happening is that chars on your system are signed. When you pass them to functions with variable number of arguments, such as printf (outside of fixed-argument portion of the signature) chars get converted to int, and they get sign-extended in the process.
To fix this, cast the value to unsigned char:
printf("\\%02hhx", (unsigned char) pt->GUID[i]);
Demo.
Answer from Sergey Kalinichenko on Stack OverflowThe reason why this is happening is that chars on your system are signed. When you pass them to functions with variable number of arguments, such as printf (outside of fixed-argument portion of the signature) chars get converted to int, and they get sign-extended in the process.
To fix this, cast the value to unsigned char:
printf("\\%02hhx", (unsigned char) pt->GUID[i]);
Demo.
Use:
printf("\%02hhx", pt->GUID[i]);
Because printf() is a variadic function, its arguments are promoted to int. The hh modifier tells printf() that the type of the corresponding value is unsigned char and not int.
You are seeing the ffffff because char is signed on your system. In C, vararg functions such as printf will promote all integers smaller than int to int. Since char is an integer (8-bit signed integer in your case), your chars are being promoted to int via sign-extension.
Since c0 and 80 have a leading 1-bit (and are negative as an 8-bit integer), they are being sign-extended while the others in your sample don't.
char int
c0 -> ffffffc0
80 -> ffffff80
61 -> 00000061
Here's a solution:
char ch = 0xC0;
printf("%x", ch & 0xff);
This will mask out the upper bits and keep only the lower 8 bits that you want.
Indeed, there is type conversion to int. Also you can force type to char by using %hhx specifier.
printf("%hhX", a);
In most cases you will want to set the minimum length as well to fill the second character with zeroes:
printf("%02hhX", a);
ISO/IEC 9899:201x says:
7 The length modifiers and their meanings are: hh Specifies that a following d, i, o, u, x, or X conversion specifier applies to a signed char or unsigned char argument (the argument will have been promoted according to the integer promotions, but its value shall be converted to signed char or unsigned char before printing); or that a following
print hex value of char
dash - How to printf ascii characters with hex or dec inside /bin/sh -c '...'? - Unix & Linux Stack Exchange
[C++] printf inserts f's when trying to print (special) char's as a hex number
Print character array as hex in C - Stack Overflow
In printf in the bash manual, you'll find:
Arguments to non-string format specifiers are treated as C language constants, except that a leading plus or minus sign is allowed, and if the leading character is a single or double quote, the value is the ASCII value of the following character.
(my emphasis)
These shell functions encapsulate char_to_hex and hex_to_char. Function names stolen from perl
# ord: the ascii value of a character
# $ ord "A" #=> 65
#
ord() {
printf "%d" "\"$1"
}
# chr: the character represented by the given ASCII decimal value
# $ chr 65 #=> A
#
chr() {
printf "\x$(printf "%x" "$1")"
}
Then:
printf '%02X\n' "$(ord A)"
41
Though short, @Juergen comments that this answers his question. Use the following:
printf "%X\n" \"A\"
Note, this provides the single-byte ("ASCII", UTF-8) charcter code. See the Unix & Linux StackExchange for more on char -> hex value and the converse, hex -> char, using bash shell and/or python.
int main(int argc, char* args[]) {
printf("%02x\n", (int) 'ê' );
return 0;
}This could should, to my understanding, print:
ea
instead it prints:
ffffffea
For "normal" char's it works as expected though, e.g.
printf("%02x\n", (int) 'j' );prints
6a
This is consistenly the case for not-normally-used-in-english characters such as ê, Ù, Ü, or Ö, and the code works as expected for "normal" characters such as j, n, ?, or k.
I'm using Eclipse CDT with MinGW.
Anyone knows why this is the case, and possibly how to fix it? Thanks in advance.
EDIT: Figured it out, apparently the problem was with the char's being signed and these special characters having too high of a value, thus overflowing. To get the correct result you have to convert them to unsigned chars first, e.g.
printf("%02x\n", (int) (unsigned char) 'ê' );
You are confused about the fuctionality of strtol. If you have a string that represents a number in hex, you can use strtol like you have:
char s[] = "ff2d";
int n = strtol(s, NULL, 16);
printf("Number: %d\n", n);
When you want to print the characters of a string in hex, use %x format specifier for each character of the string.
char s[] = "Hello";
char* cp = s;
for ( ; *cp != '\0'; ++cp )
{
printf("%02x", *cp);
}
Use %x flag to print hexadecimal integer
example.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *string = "hello", *cursor;
cursor = string;
printf("string: %s\nhex: ", string);
while(*cursor)
{
printf("%02x", *cursor);
++cursor;
}
printf("\n");
return 0;
}
output
$ ./example
string: hello
hex: 68656c6c6f
reference
- printf reference
- ascii table
This:
printf("%x", array);
will most likely print the address of the first element of your array in hexadecimal. I say "most likely" because the behavior of attempting to print an address as if it were an unsigned int is undefined. If you really wanted to print the address, the right way to do it would be:
printf("%p", (void*)array);
(An array expression, in most contexts, is implicitly converted to ("decays" to) a pointer to the array's first element.)
If you want to print each element of your array, you'll have to do so explicitly. The "%s" format takes a pointer to the first character of a string and tells printf to iterate over the string, printing each character. There is no format that does that kind of thing in hexadecimal, so you'll have to do it yourself.
For example, given:
unsigned char arr[8];
you can print element 5 like this:
printf("0x%x", arr[5]);
or, if you want a leading zero:
printf("0x%02x", arr[5]);
The "%x" format requires an unsigned int argument, and the unsigned char value you're passing is implicitly promoted to unsigned int, so this is type-correct. You can use "%x" to print the hex digits a throughf in lower case, "%X" for upper case (you used both in your example).
(Note that the "0x%02x" format works best if bytes are 8 bits; that's not guaranteed, but it's almost certainly the case on any system you're likely to use.)
I'll leave it to you to write the appropriate loop and decide how to delimit the output.
This is what I did, its a little bit easier with a function and I use for debugging and logging memory.
void print_hex_memory(void *mem) {
int i;
unsigned char *p = (unsigned char *)mem;
for (i=0;i<128;i++) {
printf("0x%02x ", p[i]);
if ((i%16==0) && i)
printf("\n");
}
printf("\n");
}
The # part gives you a 0x in the output string. The 0 and the x count against your "8" characters listed in the 08 part. You need to ask for 10 characters if you want it to be the same.
int i = 7;
printf("%#010x\n", i); // gives 0x00000007
printf("0x%08x\n", i); // gives 0x00000007
printf("%#08x\n", i); // gives 0x000007
Also changing the case of x, affects the casing of the outputted characters.
printf("%04x", 4779); // gives 12ab
printf("%04X", 4779); // gives 12AB
The "0x" counts towards the eight character count. You need "%#010x".
Note that # does not append the 0x to 0 - the result will be 0000000000 - so you probably actually should just use "0x%08x" anyway.
So i'm working on a mimic of the hexdump command in linux and for whatever reason some characters and printing properly and some are adding 6 "F" characters to the output and i'm not sure why. any insight is appreciated
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char input[20];
char chr1;
char chr2;
char magNum[8] = {};
char fType[4] = {};
printf("Filename of binary to hexdump: ");
scanf(" %s", input);
FILE *hexFile = fopen(input, "r");
if(hexFile == NULL)
{
printf("Unable to open the file\n");
exit(1);
}
printf("\nMagic Number: ");
int counter = 0;
while((chr1 = fgetc(hexFile)) != EOF)
{
if(counter == 4)
{
break;
}
printf("%0X", chr1);
fType[counter] = chr1;
counter++;
}
printf(" FileType: %s\n", fType);
printf("===============================================================================\n");
printf("| Offset | Hexadecimal Data |Character Format|\n");
printf("===============================================================================\n");
printf("| TestLne | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA |.ELF............|\n");
int lineCount = 0;
char lineString[16] = {};
fseek(hexFile, 0, SEEK_SET);
while((chr2 = fgetc(hexFile)) != EOF)
{
printf(" %0X", chr2);
}
return 0;
}