convert int to float to hex - c

Using scanf, each number typed in, i would like my program to
print out two lines: for example
byte order: little-endian
> 2
2 0x00000002
2.00 0x40000000
> -2
-2 0xFFFFFFFE
-2.00 0xC0000000
I can get it to print out the 2 in hex
but i also need a float and of course i cant scanf as one
when i need to also scan as an int
If i cast as a float when i try to printf i get a zero. If i scan in as a float
i get the correct output. I have tried to convert the int to a
float but it still comes out as zero.
here is my output so far
Int - float - hex
byte order: little-endian
>2
2 0x000002
2.00 00000000
it looks like i am converting to a float fine
why wont it print as a hex?
if i scan in as a float i get the correct hex representation like the first example.
this should be something simple. i do need to scan in as a decimal
keep in mind
i am running this in cygwin
here is what i have so far..
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int HexNumber;
float convert;
printf("Int - float - hex\n");
int a = 0x12345678;
unsigned char *c = (unsigned char*)(&a);
if (*c == 0x78)
{
printf("\nbyte order: little-endian\n");
}
else
{
printf("\nbyte order: big-endian\n");
}
printf("\n>");
scanf("%d", &HexNumber);
printf("\n%10d ",HexNumber);
printf("%#08x",HexNumber);
convert = (float)HexNumber; // converts but prints a zero
printf("\n%10.2f ", convert);
printf("%#08x", convert); // prints zeros
return 0;
}

try this:
int i = 2;
float f = (float)i;
printf("%#08X", *( (int*) &f ));
[EDIT]
#Corey:
let's parse it from inside out:
& f = address of f = say address 0x5ca1ab1e
(int*) &f = interpret the address 0x5ca1ab1e as integer pointer
* ((int*)&f) = get the integer at address 0x5ca1ab1e
the following is more concise, but it's hard to remember the C language's operator associativity and operator precedence(i prefer the extra clarity of some added parenthesis and whitespace provides):
printf("%#08X", *(int*)&f);

printf("%#08x", convert); // prints zeros
This line is not going to work because you are telling printf that you are passing in an int (by using the %x) but infact you are passing it in a float.
What is your intention with this line? To show the binary representation of the floating point number in hex? If so, you may want to try something like this:
printf("%lx\n", *(unsigned long *)(&convert));
What this line is doing is taking the address of convert (&convert) which is a pointer to a float and casting it into a pointer to an unsigned long (note: that the type you cast into here may be different depending on the size of float and long on your system). The last * is dereferencing the pointer to an unsigned long into an unsigned long which is passed to printf

Given an int x, converting to float, then printing out the bytes of that float in hex could be done something like this:
show_as_float(int x) {
float xx = x;
//Edit: note that this really prints the value as a double.
printf("%f\t", xx);
unsigned char *ptr = (unsigned char *)&xx;
for (i=0; i<sizeof(float); i++)
printf("%2.2x", ptr[i]);
}
The standards (C++ and C99) give "special dispensation" for unsigned char, so it's safe to use them to view the bytes of any object. C89/90 didn't guarantee that, but it was reasonably portable nonetheless.

Related

why itoa fuction returns 32 bits if the size of variable in 16 bit

size of short int is 2 bytes(16 bits) on my 64 bit processor and mingw compiler but when I convert short int variable to a binary string using itoa function
it returns string of 32 bits
#include<stdio.h>
int main(){
char buffer [50];
short int a=-2;
itoa(a,buffer,2); //converting a to binnary
printf("%s %d",buffer,sizeof(a));
}
Output
11111111111111111111111111111110 2
The answer is in understanding C's promotion of short datatypes (and char's, too!) to int's when those values are used as parameters passed to a function and understanding the consequences of sign extension.
This may be more understandable with a very simple example:
#include <stdio.h>
int main() {
printf( "%08X %08X\n", (unsigned)(-2), (unsigned short)(-2));
// Both are cast to 'unsigned' to avoid UB
return 0;
}
/* Prints:
FFFFFFFE 0000FFFE
*/
Both parameters to printf() were, as usual, promoted to 32 bit int's. The left hand value is -2 (decimal) in 32bit notation. By using the cast to specify the other parameter should not be subjected to sign extension, the printed value shows that it was treated as a 32 bit representation of the original 16 bit short.
itoa() is not available in my compiler for testing, but this should give the expected results
itoa( (unsigned short)a, buffer, 2 );
your problem is so simple , refer to itoa() manual , you will notice its prototype which is
char * itoa(int n, char * buffer, int radix);
so it takes an int that to be converted and you are passing a short int so it's converted from 2 byte width to 4 byte width , that's why it's printing a 32 bits.
to solve this problem :
you can simply shift left the array by 16 position by the following simple for loop :
for (int i = 0; i < 17; ++i) {
buffer[i] = buffer[i+16];
}
and it shall give the same result , here is edited version of your code:
#include<stdio.h>
#include <stdlib.h>
int main(){
char buffer [50];
short int a= -2;
itoa(a,buffer,2);
for (int i = 0; i < 17; ++i) {
buffer[i] = buffer[i+16];
}
printf("%s %d",buffer,sizeof(a));
}
and this is the output:
1111111111111110 2

Get float in HEX format

I have the string char str [8]. It says a number in the HEX format. It is float and with a sign. How can I write it to a variable of type float?
For example:
char str[9] = "41700000\0";
I need get val from this: 15.0
You can pun the data:
Using memcpy
unsigned int u = 0x41700000;
float f;
memcpy(&f, &u, sizeof(f));
printf("%f\n", f);
Using union (IMO legal, many people have opposite opinion)
union un
{
float f;
unsigned u;
};
void foo(unsigned x)
{
union un a = {.u = x};
printf("%f\n", a.f);
}
I assume floats && integers have the same size.
Of course you will have to convert string from your question to the unsigned value - but it is relatively easy (scanf, atoi ....)
PS BTW many compilers will generate exactly the same code for both (without the memcpy call) https://godbolt.org/z/VaCcxS
This is a quick and dirty way to revert your 15 back from the hexadecimal 4 bytes representation. There is too much wrong with it to even start talking about it, though, and the right thing to do would be to ask yourself "why do i need this to begin from, and how can i do something better instead".
float hexStrToFloat(const char* str)
{
union { unsigned int i; float f; } tmp;
sscanf_s(str, "%x", &tmp.i);
return(tmp.f);
}
Footnote: assumes little-endian, 32 bit or higher, machine.

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.

Displaying floating point variable as a hex integer screws up neighbouring integer

I have this simple program
#include <stdio.h>
int main(void)
{
unsigned int a = 0x120;
float b = 1.2;
printf("%X %X\n", b, a);
return 0;
}
I expected the output to be
some-value 120 (some-value will depend on the bit pattern of `float b` )
But I see
40000000 3FF33333
Why is the value of a getting screwed up? %X treats its arguments as signed int and hence it should have retrieved 4 bytes from the stack and printed the calue of b and then fetching the next 4 bytes print the value of a which is 0x120
Firstly, it's undefined behaviour to pass arguments to printf not matching the format specifiers.
Secondly, the float is promoted to double when passed to printf, so it's eight bytes instead of four. Which bytes get interpreted as the two unsigned values expected by the printf format depends on the order in which the arguments are pushed.
If you want to see the bits of a stored float, use a union:
float b = 1.2;
union {
float f;
int i;
} u;
u.f = b;
printf ("%x\n", u.i);
results (32-bit x86):
3f99999a

Convert ieee 754 float to hex with c - printf

Ideally the following code would take a float in IEEE 754 representation and convert it into hexadecimal
void convert() //gets the float input from user and turns it into hexadecimal
{
float f;
printf("Enter float: ");
scanf("%f", &f);
printf("hex is %x", f);
}
I'm not too sure what's going wrong. It's converting the number into a hexadecimal number, but a very wrong one.
123.1443 gives 40000000
43.3 gives 60000000
8 gives 0
so it's doing something, I'm just not too sure what.
Help would be appreciated
When you pass a float as an argument to a variadic function (like printf()), it is promoted to a double, which is twice as large as a float (at least on most platforms).
One way to get around this would be to cast the float to an unsigned int when passing it as an argument to printf():
printf("hex is %x", *(unsigned int*)&f);
This is also more correct, since printf() uses the format specifiers to determine how large each argument is.
Technically, this solution violates the strict aliasing rule. You can get around this by copying the bytes of the float into an unsigned int and then passing that to printf():
unsigned int ui;
memcpy(&ui, &f, sizeof (ui));
printf("hex is %x", ui);
Both of these solutions are based on the assumption that sizeof(int) == sizeof(float), which is the case on many 32-bit systems, but isn't necessarily the case.
When supported, use %a to convert floating point to a standard hexadecimal format. Here is the only document I could find that listed the %a option.
Otherwise you must pull the bits of the floating point value into an integer type of known size. If you know, for example, that both float and int are 32 bits, you can do a quick cast:
printf( "%08X" , *(unsigned int*)&aFloat );
If you want to be less dependent on size, you can use a union:
union {
float f;
//char c[16]; // make this large enough for any floating point value
char c[sizeof(float)]; // Edit: changed to this
} u;
u.f = aFloat;
for ( i = 0 ; i < sizeof(float) ; ++i ) printf( "%02X" , u.c[i] & 0x00FF );
The order of the loop would depend on the architecture endianness. This example is big endian.
Either way, the floating point format may not be portable to other architectures. The %a option is intended to be.
HEX to Float
I spend quite a long time trying to figure out how to convert a HEX input from a serial connection formatted as IEE754 float into float. Now I got it. Just wanted to share in case it could help somebody else.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
uint16_t tab_reg[64] //declare input value recieved from serial connection
union IntFloat { int32_t i; float f; }; //Declare combined datatype for HEX to FLOAT conversion
union IntFloat val;
int i;
char buff[50]; //Declare buffer for string
i=0;
//tab_reg[i]=0x508C; //to test the code without a data stream,
//tab_reg[i+1]=0x4369; //you may uncomment these two lines.
printf("Raw1: %X\n",tab_reg[i]); //Print raw input values for debug
printf("Raw2: %X\n",tab_reg[i+1]); //Print raw input values for debug
rs = sprintf(buff,"0X%X%X", tab_reg[i+1], tab_reg[i]); //I need to swap the words, as the response is with the opposite endianness.
printf("HEX: %s",buff); //Show the word-swapped string
val.i = atof(buff); //Convert string to float :-)
printf("\nFloat: %f\n", val.f); //show the value in float
}
Output:
Raw1: 508C
Raw2: 436A
HEX: 0X436A508C
Float: 234.314636
This approach always worked pretty fine to me:
union converter{
float f_val;
unsigned int u_val;
};
union converter a;
a.f_val = 123.1443f;
printf("my hex value %x \n", a.u_val);
Stupidly simple example:
unsigned char* floatToHex(float val){
unsigned char* hexVals = malloc(sizeof(float));
hexVals[0] = ((unsigned char*)&val)[0];
hexVals[1] = ((unsigned char*)&val)[1];
hexVals[2] = ((unsigned char*)&val)[2];
hexVals[3] = ((unsigned char*)&val)[3];
return hexVals;
}
Pretty obvious solution when I figured it out. No bit masking, memcpy, or other tricks necessary.
In the above example, it was for a specific purpose and I knew floats were 32 bits. A better solution if you're unsure of the system:
unsigned char* floatToHex(float val){
unsigned char* hexVals = malloc(sizeof(float));
for(int i = 0; i < sizeof(float); i++){
hexVals[i] = ((unsigned char*)&val)[i];
}
return hexVals;
}
How about this:?
int main(void){
float f = 28834.38282;
char *x = (char *)&f;
printf("%f = ", f);
for(i=0; i<sizeof(float); i++){
printf("%02X ", *x++ & 0x0000FF);
}
printf("\n");
}
https://github.com/aliemresk/ConvertD2H/blob/master/main.c
Convert Hex to Double
Convert Double to Hex
this codes working IEEE 754 floating format.
What finally worked for me (convoluted as it seems):
#include <stdio.h>
int main((int argc, char** argv)
{
float flt = 1234.56789;
FILE *fout;
fout = fopen("outFileName.txt","w");
fprintf(fout, "%08x\n", *((unsigned long *)&flt);
/* or */
printf("%08x\n", *((unsigned long *)&flt);
}

Resources