I wrote a program to convert float to it's binary IEEE754 representation in C.
Any improvements to this is appreciated
#include <stdio.h>
#include <stdlib.h>
void binary(float num) {
int n = *(int *) # //Evil bit hack from Quake3 Q_sqrt function
int size = sizeof(n) * 8;
char *s = malloc(1 + size); //A string which can hold 32 characters
s[size] = '0円';
int index = size - 1;
while(index >= 0) {
if (n & 1)
*(s + index) = '1';
else
*(s + index) = '0';
n >>= 1;
index--;
}
printf("%s\n", s);
free(s);
}
int main(void) {
float num;
scanf("%f", &num);
binary(num);
}
1 Answer 1
IEEE754 conformance
Compilers aren't required to support IEEE754 decimals. Most implementations do, but regardless, it's better to check for maximum portability. If you're using C99 or later, the macro __STDC_IEC_559__
is defined whenever IEEE754 is supported.
sizeof(int)
Similarly, int
isn't guaranteed to be 32 bits. The compiler only guarantees a minimum size of 16 bits. You can use the fixed width integer types defined in stdint.h
i.e. uint32_t
or int32_t
.
Use size_t
instead of int
The proper type for sizeof
expression is size_t
. As a general use, any variable representing size or index should be size_t
.
Since you're not using s
outside of the binary
function, you can just allocate a fixed an array of size 33 on the stack instead of on the heap using malloc
.
static const size_t num_bits = 33;
char s[num_bits];
*(s + index)
is just fancy way to write s[index]
. The latter is much cleaner, IMO and much more easier to understand for someone who isn't familiar with pointer arithmetic.
-
\$\begingroup\$ The benefit of the stack usage change cannot be underestimated .. Memory allocation is much much slower (even just the overhead of a function call) than just referencing the space the compiler has allowed for / left (compile time cost for runtime benefit !!). \$\endgroup\$Mr R– Mr R2021年05月01日 00:27:15 +00:00Commented May 1, 2021 at 0:27
-
2\$\begingroup\$ Your wording about IEEE754 conformance is slightly incorrect. It's the C standard that does not require an implementation to support IEEE754. However, the compilers themselves are not free to choose what they implement, they are bound by what the platform ABI specifies the format of
float
anddouble
should be. The same goes for the size of integer types. \$\endgroup\$G. Sliepen– G. Sliepen2021年05月01日 07:25:59 +00:00Commented May 1, 2021 at 7:25 -
\$\begingroup\$ Hmm, I was not aware of that but it makes sense. Thanks! \$\endgroup\$Rish– Rish2021年05月01日 08:34:55 +00:00Commented May 1, 2021 at 8:34
-
\$\begingroup\$ @Rish Thanks for the answer, Although I don't understand why all compilers not use IEEE 754 representation to store
float
. If not, what's the most common way to store floats or double(To be precise single/double precision literals)? By the way, I'm compiling the above program on gcc shipped with ubuntu LTS \$\endgroup\$C--– C--2021年05月01日 13:51:43 +00:00Commented May 1, 2021 at 13:51 -
1\$\begingroup\$ @G.Sliepen C is popularly used in embedded situations where the is no ABI specifics and compiler can use any FP encoding. Even in ABI specifics, that often refers to the encoding only. Complete adherence to quality handling of sub-normals, -0.0, inf, NaN is wide ranging. Certainly interface requirements strongly influence the code a compiler makes, yet there remains much wiggle room. In the case were the processor directly implements FP, that tends to dominate. Yet without FP hardware (100s of millions/yr of those little embedded processors), be prepared for variety. \$\endgroup\$chux– chux2021年05月07日 11:51:25 +00:00Commented May 7, 2021 at 11:51
float
or "convert float to it's binary IEEE754" (even whenfloat
is not encoded as IEEE754)? \$\endgroup\$