Char to Hex not showing string's ASCII value - c

Playing around with C or C99, i'm trying to understand how casting, bitshifts, and Hex values work.
I have an issue with the following
char c[4];
c[0] = 0x41;
c[1] = 0x42;
c[2] = 0x43;
c[3] = 0x00;
printf("%s", c); //prints ABC
printf("%X", c); //prints 99B11760
Where does 99B11760 come from?
So similarly...
int main() {
char a = 'a'; //ascii value is 0x41 (Mistake I made, 'a' is 0x61, 'A' is 0x41)
printf("%X\n",a); //outputs "61"? (THIS IS CORRECT OUTPUT, 'a' != 0x41)
}
I keep finding solutions to how to solve a similar problems of storing Hex values into char, but what I'm having trouble understanding is why or where some stored values do not correspond to it's ASCII values. Since it's neither the ASCII hex value, dec value, or octal Value, what value is being printed when using printf("%X\n", c);

an array variable in C is allowed to automatically convert into an address value (a.k.a a pointer value). The output you're seeing has absolutely no relation to the content of your array.
Perhaps you meant to do this?
char c[4];
c[0] = 0x41;
c[1] = 0x42;
c[2] = 0x43;
c[3] = 0x00;
printf("%X", *(unsigned int*)c );

Where does 99B11760 come from?
It's the value c happened to have after you forced it to decay into a pointer.
I keep finding solutions to how to solve this problem
What problem? Is there something you are trying to do that you don't know how to do? "I did something that made no sense and got a nonsense answer" isn't a problem. Just don't do that.
.. but what I'm having trouble with is understanding why or where 61 is being printed instead of the ASCII hex value 0x41. It's not the decimal value, nor the Octal value.
As you see, there is no particular value that it should be. But it has to be something. If you throw a die up in the air and it comes down with a 2, do you wonder why it's a 2? Of course not. You only have an issue when it should be one thing but is another. In this case, there's nothing it should be.

printf("%X", c); //prints 99B11760
This invokes undefined behavior. x conversion specifier expects an unsigned int but you are passing a char *.
In your second part of your question, you should cast a to unsigned int.
printf("%X\n", (unsigned int) a);
A ascii value is 0x41, but a ascii value is 0x61.

For the first question, when you print c using %X format it is printing the address of the array (address of first character). For the second question , this is because ASCII value of a is 97 (decimal) which converted to hex is 61. If you use A character then it will print 41 as the ASCII value of capital A is 65.

c is a pointer so when you print it using anything but %s you will get the pointer address printed.

int main() {
char a = 'a'; //ascii value is 0x41
printf("%X\n",a); //outputs "61"?
}
In this case, first you are storing 'a'(ascii value = 97) into character a, so character a contains 97, then you are printing 97 in hex form as "0x61"
char c[4];
c[0] = 0x41;
c[1] = 0x42;
c[2] = 0x43;
c[3] = 0x00;
printf("%s", c); //prints ABC
printf("%X", c); //prints 99B11760
in this case
'0x41' in decimal value is 65 is 'A' in ASCII
'0x42' in decimal value is 66 is 'B' in ASCII
'0x43' in decimal value is 67 is 'C' in ASCII
'0x00' in decimal value is 00 is null in ASCII
It will output 'ABC ' if format specifier is char/string type

Related

Hebrew char translates to "FFFF" in HEX

I have a code that translates ASCII char array to a Hex char array:
void ASCIIFormatCharArray2HexFormatCharArray(char chrASCII[72], char chrHex[144])
{
int i,j;
memset(chrHex, 0, 144);
for(i=0, j=0; i<strlen(chrASCII); i++, j+=2)
{
sprintf((char*)chrHex + j, "%02X", chrASCII[i]);
}
chrHex[j] = '\0';
}
When I insert the function the char 'א' - Alef, the equivalent to 'A' in English, the function does this:
chrHex = "FFFF"
I don't understand how 1 char translates to 2 bytes of Hex ("FFFF") instead of 1 byte(like "u" in ASCII is "75" in Hex) when it's not even an English letter.
would love for an explanation of how the compiler treats 'א' like so.
When “א” appears in a string literal, your compiler likely represents it with the bytes D716 and 9016, although other possibilities are allowed by the C standard.
When these bytes are interpreted as a signed char, they have the values −41 and −112. When these are passed as an argument to sprintf, they are automatically promoted to int. In a 32-bit two’s complement int, the bits used to represent −41 and −112 are FFFFFFD716 and FFFFFF9016.
The behavior of asking sprintf to format these with %02X is technically not defined by the C standard, because an unsigned int should be passed for X, rather than an int. However, your C implementation likely formats them as “FFFFFFD7” and “FFFFFF90”.
So the first sprintf puts “FFFFFFD7” in chrHex starting at element 0.
Then the second sprintf puts “FFFFFF90” in chrHex starting at element 2, partially overwriting the first string. Now chrHex contains “FFFFFFFF90”.
Then chrHex[j] = '\0'; puts a null character an element 4, truncating the string to “FFFF”.
To fix this, change the sprintf to expect an unsigned char and pass an unsigned char value (which will be promoted to int, but sprintf expects that for hhX and works with it):
sprintf(chrHex + j, "%02hhX", (unsigned char) chrASCII[i]);

Character plus number in C

I have this code:
#include <stdio.h>
int main()
{
char c1;
c1 ='A' +4;
printf("c1 = %c\n", c1);
}
and i get this output:
c1 = E
Can someone please explain it?
The ASCII value of English letter A is 65, B's 66 ... and E's 69.
The syntax:
c1 = 'A' + 4;
Gets converted into (since printf() uses %c specifier to represent c1):
c1 = 69; // 'A' holds 65 (implicitly converted into an integer before \
// performing assignment.)
And when it's again converted into char, it displays letter E.
Take a look at ASCII table to get to know more about ASCII values.
It works on ASCII values. You have assigned A in varibale c1 and ASCII valie of A is 65. Than you have added 4 so it will become 65+4=69 now printf will look 69 belongs to which character 69 belongs to letter E
ASCII values A-Z 65,66, ... ,90
values a-z 97,98 , ... ,122
In computers, everything is represented by numbers. Even each letter has its number. In the ASCII (American Standard Code for Information Interchange) encoding created by ANSI (American National Standards Institute), the values for each character are following:
In the char datatype, this are the numbers that are stored.
In C, character literals such as 'A' are of type int. 'A' would be 65 as you can see in the table.
Therefore if you do:
char c1;
c1 = 'A' + 4;
then
'A' + 4 equals 65 + 4 equals 69 equals 'E'
Then you supply it to printf with %c specifier, which prints it as a character instead of a number.

c and bit shifting in a char

I am new to C and having a hard time understanding why the code below prints out ffffffff when binary 1111111 should equal hex ff.
int i;
char num[8] = "11111111";
unsigned char result = 0;
for ( i = 0; i < 8; ++i )
result |= (num[i] == '1') << (7 - i);
}
printf("%X", bytedata);
You print bytedata which may be uninitialized.
Replace
printf("%X", bytedata);
with
printf("%X", result);
Your code then run's fine. code
Although it is legal in C, for good practice you should make
char num[8] = "11111111";
to
char num[9] = "11111111";
because in C the null character ('\0') always appended to the string literal. And also it would not compile as a C++ file with g++.
EDIT
To answer your question
If I use char the result is FFFFFFFF but if I use unsigned char the result is FF.
Answer:
Case 1:
In C size of char is 1byte(Most implementation). If it is unsigned we can
use 8bit and hold maximum 11111111 in binary and FF in hex(decimal 255). When you print it with printf("%X", result);, this value implicitly converted to unsigned int which becomes FF in hex.
Case 2: But when you use char(signed), then MSB bit use as sign bit, so you can use at most 7 bit for your number whose range -128 to 127 in decimal. When you assign it with FF(255 in decimal) then Integer Overflow occur which leads to Undefined behavior.

what is difference between 9-'0' and '9'-'0' in C?

In my following code:
main(){
int c;
char c1='0';
int x=9-c1;
int y='9'-c1;
}
Now in this program I'm getting value of x as some arbitrary value, but the value of y is 0, which is the value that I expect. Why this difference?
Here is a good explanation. Just compile it and run:
#include <stdio.h>
int main(){
int c;
char c1='0';
int x=9-c1;
int y='9'-c1;
printf("--Code and Explanation--\n");
printf("int c;\n");
printf("char c1='0';\n");
printf("int x=9-c1;\n");
printf("int y='9'-c1;\n");
printf("c1 as char '0' has decimal value: %d\n", c1);
printf("decimal 9 - decimal %d or c1 = %d or x\n", c1, x);
printf("char '9' has decimal value %d - decimal %d or c1 = %d\n", '9', c1, y);
printf("Your Welcome :)\n");
return 0;
}
1st char are integers.
2nd chars might have a printable representation or output controlling function (like for ASCII: TAB, CR, LF, FF, BELL ...) depending on the character set in use.
For ASCII
char c = 'A';
is the same as
char c = 65;
is the same as
char c = 0x41;
Another character set widely in use for example is EBCDIC. It uses a different mapping of a character's integer value to its printable/controling representation.
Internally always the same integer value is used/stored.
The printable, often but not always ASCII representation of, for example 65 or 0x41, which is A, is only used when
either printing out using the printf()-family along with the conversion specifiers %s or %c or puts()
or scanning in using the scanf()-family along with the conversion specifiers %s or %c or fgets()
or when coding literals like 'A' or "ABC".
On all other operation only the char's integer value is used.
When you do calculations with chars, you have to keep in mind that to you it looks like a '0' or '9', but the compiler interprets is as its ASCII value, which is 48 for '0' and 57 for '9'.
So when you do:
int x=9-c1;
the result is 9 - 48 = -39. And for
int y='9'-c1;
the result is 57 - 48 = 9.
According to the C Standard (5.2.1 Character sets)
...In both the source and execution basic character sets, the value of
each character after 0 in the above list of decimal digits shall be
one greater than the value of the previous.
Thus expression '9' - '0' has the same value like 9 - 0 and is equal to 9 whether you are using for example the ASCII table of characters or the EBCDIC.
Expression 9 - '0' is implementation defined and depends on the coding table you are using. But in any case the value of the internal representation of character '0' is greater then 9. (9 is the value of the tab character representation '\t')
For example in the ASCII the value of the code of character '0' is equal to 48.
In the EBCDIC the value of '0' is equal to 240.
So you will get that 9 - '0' is some negative number.
For example it is equal to -39 if the character representations are based on the ASCII table or -231 if the character representations are based on the EBCDIC table.
You can see this yourself running this simple program
#include <stdio.h>
int main( void )
{
printf( "%d\n", 9 - '0' );
}
You could write the printf statement also in the following way;)
printf( "%d\n", '\t' - '0' );
because 9 as I mentioned is the value of the internal representation of the escape character '\t' (tab).

How to print the hexadecimal in a specific manner?

In the following code I stored the mac address in a char array.
But even when I am storing it in a char variable, while printing it's printing as follows:
ffffffbb
ffffffcc
ffffffdd
ffffffee
ffffffff
This is the code:
#include<stdio.h>
int main()
{
char *mac = "aa:bb:cc:dd:ee:ff";
char a[6];int i;
sscanf(mac,"%x:%x:%x:%x:%x:%x",&a[0],&a[1],&a[2],&a[3],&a[4],&a[5]);
for( i = 0; i < 6;i++)
printf("%x\n",a[i]);
}
I need the output to be in the following way:
aa
bb
cc
dd
ee
ff
The current printf statement is
printf("%x\n",a[i]);
How can I get the desired output and why is the printf statement printing ffffffaa even though I stored the aa in a char array?
You're using %x, which expects the argument to be unsigned int *, but you're just passing char *. This is dangerous, since sscanf() will do an int-sized write, possibly writing outside the space allocated to your variable.
Change the conversion specifier for the sscanf() to %hhx, which means unsigned char. Then change the print to match. Also, of course, make the a array unsigned char.
Also check to make sure sscanf() succeded:
unsigned char a[6];
if(sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
a, a + 1, a + 2, a + 3, a + 4, a + 5) == 6)
{
printf("daddy MAC is %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
a[0], a[1], a[2], a[3], a[4], a[5]);
}
Make sure to treat your a array as unsigned chars, i.e.
unsigned char a[6];
In
printf("%x\n",a[i]);
the expression a[i] yields a char. However, the standard does not specify whether char is signed or unsigned. In your case, the compiler apparently treats it as a signed type.
Since the most significant bit is set in all the bytes of your Mac address (each by is larger than or equal to 0x80), a[i] is treated as a negative value so printf generates the hexadecimal representation of a negative value.

Resources