C - Missing 0 in hexadecimal output - c

I had to test if my machine is using the little or the big endian. For this reason i wrote this code. I can see that my machine is using the little endian. But i dont know why the output from my first byte is only D. Should it not be 0D?
union int2byte
{
unsigned char bytes[4];
unsigned int hex;
};
int main(int argc, const char* argv[])
{
union int2byte hexby;
hexby.hex = 0xBAADF00D;
printf("%u\n",hexby.hex);
int counter;
for(counter = 0; counter < 4; counter = counter + 1)
{
printf("Hex for Byte %u is %X.\n",counter+1, hexby.bytes[counter]);
}
}
Output:
3131961357
Hex for Byte 1 is D.
Hex for Byte 2 is F0.
Hex for Byte 3 is AD.
Hex for Byte 4 is BA.

%X does not output leading zeros. Use %02X instead. The 2 tells it to output at least 2 digits, and the 0 tells it to pad the output on the left side with a '0' character if the output is less than 2 digits.

Related

Displaying integer in a special hexadecimal format

i am again facing a formatting problem. I want to pass a port number (as integer) as parameter to a function (argv[]) and want to display it in a special format. In my actual case i want to display the port number 1234 in hexadecimal. I try it this way
int port = 1234;
char* _port = (char*)&port;
for (int i = 0; i < sizeof(port); i++) {
printf("\\x%02x", _port[i]);
}
but it shows
\xffffffd2\x04\x00\x00
But i want it in format with leading zeros and 2 digits like
\x04\xd2
can you help me please?
EDIT: I changed it to
sizeof(port)-2
and it shows only 2 digits but in the wrong endian :S
On most systems the size of int is four bytes, 32 bits. The hexadecimal representation of 1234 is 0x000004d2. On a little-endian system (like x86 and x86-64) it's stored in memory like the four bytes 0xd2, 0x04, 0x00 and 0x00 in that order.
If we look at it as an array of bytes, it looks like
+------+------+------+------+
| 0xd2 | 0x04 | 0x00 | 0x00 |
+------+------+------+------+
There are three problems you have:
You loop over all four bytes of the int, while you only want the significant bits
You don't consider the endianness
That char on your system is signed and when promoted to int it will be sign-extended (according to the two's complement rules)
To solve the first point you need to discard the "leading" zero bytes.
To solve the second point you need to loop from the end (but only on little-endian systems).
To solve the third point use a type which won't be sign-extended (i.e. uint8_t).
Put together you could do something like this:
// The number we want to print
int port = 1234;
// Copy the raw binary data to a buffer
// This buffer is to not break strict aliasing
uint8_t _port[sizeof port];
memcpy(_port, &port, sizeof port);
// Skip leading zeroes in the buffer
// This is done by looping from the end of the buffer to the beginning,
// and loop as long as the current byte is zero
uint8_t *current;
for (current = _port + sizeof _port - 1; current > _port && *current == 0; --current)
{
// Empty
}
// Print the remaining bytes
for (; current >= _port; --current)
{
printf("\\x%02x", *current); // Print with zero-padding, so e.g. \x4 becomes \x04
}
Proof of concept
Get rid of signess and modify the formats.
void foo(int port, int endianess)
{
unsigned char * _port = (unsigned char*)&port;
if(endianess)
{
for (size_t i = 0; i < 2; i++)
{
printf("\\x%02hhx", _port[i]);
}
}
else
{
for (size_t i = sizeof(port) - 1; i >= sizeof(port) - 2; i--)
{
printf("\\x%02hhx", _port[i]);
}
}
}

How to convert binary int array to hex char array?

Say I have a 32 bit long array of 32 binary digits and I want to output that in Hex form. How would I do that? this is what I have right now but it is too long and I don't know how to compare the 4 binary digits to the corresponding hex number
This is what I have right now where I break up the 32 bit number into 4 bit binary and try to find the matching number in binaryDigits
char hexChars[16] ={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
char * binaryDigits[16] = {"0000","0001","0010","0011","0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111"};
int binaryNum[32]= {'0','0','1','0','0','0','0','1','0','0','0','0','1','0','0','1','0','0','0','0','0','0','0','0','0','0','0','0','1','0','1','0'};
int currentBlock, hexDigit;
int a=0, b=1, i=0;
while (a<32)
{
for(a=i+3;a>=i;a--)
{
current=binaryNum[a];
temp=current*b;
currentBlock=currentBlock+temp;
b*=10;
}
i=a;
while(match==0)
{
if(currentBlock != binaryDigits[y])
y++;
else
{
match=1;
hexDigit=binaryDigits[y];
y=0;
printf("%d",hexDigit);
}
}
}
printf("\n%d",currentBlock);
I apologize if this isn't the crux of your issue, but you say
I have a 32 bit long array of 32 binary digits
However, int binaryNum[32] is a 32-integer long array (4 bytes per int, 8 bits per byte = 4 * 8 * 32 which is (1024 bits)). That is what is making things unclear.
Further, you are assigning the ASCII character values '0' (which is 0x30 hex or 48 decimal) and '1' (0x31, 49) to each location in binaryNum. You can do it, and do the gymnastics to compare each value to actually form a
32 bit long array of 32 binary digits
but if that is what you have, why not just write it that way? (as a binary constant). That will give you your 32-bit binary value. For example:
#include <stdio.h>
int main (void) {
unsigned binaryNum = 0b00100001000010010000000000001010;
printf ("\n binaryNum : 0x%8x (%u decimal)\n\n", binaryNum, binaryNum);
return 0;
}
Output
$ ./bin/binum32
binaryNum : 0x2109000a (554237962 decimal)
If this is not where your difficulty lies, please explain further, or again, just what you are trying to accomplish.

Right shift in C

I am trying to get a hexadecimal memory address from a text file and shift the 3 most bits and then print the result.
The memory address is A3BC88A0 and I just want to print A3BC8? However, when I run the code, addr = A3BC88AO but result = 14779114. Can someone help me figure out why this is happening or what to do?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char * argv[])
{
FILE *f;
myfile = fopen("Test.txt", "r");
unsigned addr;
fscanf(f, "%x", &addr);
printf("%x\n",addr);
unsigned result = addr >> 3;
printf("%x\n",result);
fclose(myfile);
return 0;
}
What you want is not to shift by 3 bits, but by 3 hex digits, each of which is 4 bits. So do this instead:
unsigned result = addr >> 12;
The >> 3 shifts the value by 3 bits, however you asked for A3BC88A0 to be shifted by 3 nybbles (half bytes) to result in A3BC8
Change the line to:
unsigned result = addr >> (3*4);
(I put the 3*4 rather than just 12 to highlight that its nybbles you want to shift by).
Note for clarity: A single hex digit is 4 bits, which is half a byte, which is a nybble (not a very common term admittedly)

Confusion on printing strings as integers in C

I would like to know how the string is represented in integer, so I wrote the following program.
#include <stdio.h>
int main(int argc, char *argv[]){
char name[4] = {"#"};
printf("integer name %d\n", *(int*)name);
return 0;
}
The output is:
integer name 64
This is understandable because # is 64 in integer, i.e., 0x40 in hex.
Now I change the program into:
#include <stdio.h>
int main(int argc, char *argv[]){
char name[4] = {"##"};
printf("integer name %d\n", *(int*)name);
return 0;
}
The output is:
integer name 16448
I dont understand this. Since ## is 0x4040 in hex. So it should be 2^12+2^6 = 4160
If I count the '\0' at the end of the string, then it should be 2^16+2^10 = 66560
Could someone explain where 16448 comes from?
Your math is wrong: 0x4040 == 16448. The two fours are the 6th and 14th bits respectively.
Your code actually invokes undefined behavior because you must not alias a char * with an int *. This is known as the strict aliasing rule. To see just one reason why this should be disallowed, consider what would otherwise have to happen if the code is run on a little and a big endian machine.
If you want to see the hex pattern of the string, you should simply loop over its bytes and print out each byte.
void
print_string(const char * strp)
{
printf("0x");
do
printf("%02X", (unsigned char) *strp);
while (*strp++);
printf("\n");
}
Of course, instead of printing the bytes, you can shift them into an integer (that will very soon overflow) and only finally output that integer. While doing this, you'll be forced to take a stand on “your” endianness.
/* Interpreting as big endian. */
unsigned long
int_string(const char * strp)
{
unsigned long value = 0UL;
do
value = (value << 8) | (unsigned char) *strp;
while (*strp++);
return value;
}
This is how 16448 comes :
0x4040 can be written like this in binary :
4 0 4 0 -> Hex
0100 0000 0100 0000 -> Binary
2^14 2^6 = 16448
Because here 6th and 14th bit are set.
Hope you got it :)

Why does C print my hex values incorrectly?

So I'm a bit of a newbie to C and I am curious to figure out why I am getting this unusual behavior.
I am reading a file 16 bits at a time and just printing them out as follows.
#include <stdio.h>
#define endian(hex) (((hex & 0x00ff) << 8) + ((hex & 0xff00) >> 8))
int main(int argc, char *argv[])
{
const int SIZE = 2;
const int NMEMB = 1;
FILE *ifp; //input file pointe
FILE *ofp; // output file pointer
int i;
short hex;
for (i = 2; i < argc; i++)
{
// Reads the header and stores the bits
ifp = fopen(argv[i], "r");
if (!ifp) return 1;
while (fread(&hex, SIZE, NMEMB, ifp))
{
printf("\n%x", hex);
printf("\n%x", endian(hex)); // this prints what I expect
printf("\n%x", hex);
hex = endian(hex);
printf("\n%x", hex);
}
}
}
The results look something like this:
ffffdeca
cade // expected
ffffdeca
ffffcade
0
0 // expected
0
0
600
6 // expected
600
6
Can anyone explain to me why the last line in each block doesn't print the same value as the second?
The placeholder %x in the format string interprets the corresponding parameter as unsigned int.
To print the parameter as short, add a length modifier h to the placeholder:
printf("%hx", hex);
http://en.wikipedia.org/wiki/Printf_format_string#Format_placeholders
This is due to integer type-promotion.
Your shorts are being implicitly promoted to int. (which is 32-bits here) So these are sign-extension promotions in this case.
Therefore, your printf() is printing out the hexadecimal digits of the full 32-bit int.
When your short value is negative, the sign-extension will fill the top 16 bits with ones, thus you get ffffcade rather than cade.
The reason why this line:
printf("\n%x", endian(hex));
seems to work is because your macro is implicitly getting rid of the upper 16-bits.
You have implicitly declared hex as a signed value (to make it unsigned write unsigned short hex) so that any value over 0x8FFF is considered to be negative. When printf displays it as a 32-bit int value it is sign-extended with ones, causing the leading Fs. When you print the return value of endian before truncating it by assigning it to hex the full 32 bits are available and printed correctly.

Resources