简体   繁体   中英

Need help understanding code converting doubles to binary in C

so below is some code which I am using to understand how to get the binary of a double in C however there are some areas of the code which do not make sense to me and I have tried using print statements to help me but to no avail

#include <stdio.h>
#include <string.h>
#include <limits.h>

void double_to_bits(double val);

int main(void)
{
    unsigned idx;

    double vals[] = { 10 };

    for (idx = 0; idx < 4; idx++ ) {
        printf("\nvals[%u]= %+lf-->>", idx, vals[idx] );
        double_to_bits(vals[idx] );
    }
    printf("\n");

    return 0;
}

void double_to_bits(double val)
{
    unsigned idx;
    unsigned char arr[sizeof val];

    memcpy (arr, &val, sizeof val);
    printf("array is : %s\n", arr);

    for (idx=CHAR_BIT * sizeof val; idx-- ; ) {
        putc(
                ( arr[idx/CHAR_BIT] & (1u << (idx%CHAR_BIT) ) )
                ? '1'
                : '0'
                , stdout
        );
    }
}

What does arr[idx/CHAR_BIT] return? I understand say if idx = 63 then we get arr[7] but in print statements these seem to just give random integer values .

Also why does the & operand between arr[idx/CHAR_BIT] and (1u%CHAR_BIT) give 2 weird character symbols? How does the & operand work on these two values?

Thank you for your time and help.

This code defines vals to have one element:

    double vals[] = { 10 };

This code uses vals as if it has four elements:

    for (idx = 0; idx < 4; idx++ ) {
        printf("\nvals[%u]= %+lf-->>", idx, vals[idx] );
        double_to_bits(vals[idx] );
    }

Because of that, the behavior of the program is not defined by the C standard, and different compilers will do different things. You have not shown us what output you get, so we have no way to analyze what your compiler did. Mine seems to figure that, since vals has only one element, it never needs to bother computing the value of idx in vals[idx] ; it can always use vals[0] . So every iteration operates on the value 10. Your compiler may have loaded from memory outside the array and used different values.

What does arr[idx/CHAR_BIT] return?

CHAR_BIT is defined in <limits.h> to be the number of bits in a byte. Because of the definition unsigned char arr[sizeof val]; , arr is an array with as many elements (each one byte) as there are bytes in a double . So, for example, if there are 8 bits in a byte and 8 bytes in a double , then arr has 8 8-bit elements, 64 bits total.

Using these example numbers, the for loop iterates idx through the numbers from 63 to 0. Then the code uses idx as a counter of the bits in arr . The expression idx/CHAR_BIT figures out which element of the array contains the bit numbered idx : Each array element has CHAR_BIT bits, bits 0-7 (when CHAR_BIT is 8) are in element 0, bits 8-15 are in element 1, bits 16-23 are in element 2, and so on. So dividing idx by CHAR_BIT and truncating to an integer (which is what the / operator does for integer operands) gives the index of the array element that has the bit with number idx .

Then arr[idx/CHAR_BIT] gets that element. Then we need to pick out the individual bit from that element. idx%CHAR_BIT takes the remainder of idx divided by CHAR_BIT , so it gives the number of a bit within a byte. Then 1u << (idx%CHAR_BIT) shifts 1 by that number. The result is number that, when expressed in binary, has a 1 in the bit with that number and a 0 in other bits.

Then the & operator ANDs that with the array element. If the array element has a 0 where the 1 has been shifted to, the result is zero. If the array element has a 1 where the 1 has been shifted to, the result is that bit (still in its position).

Then ? '1' : '0;' ? '1' : '0;' uses the result of that AND to select either the character '1' (if the result is not zero) or the character '0' (if the result is zero). That character is passed to putc for printing.

I understand say if idx = 63 then we get arr[7] but in print statements these seem to just give random integer values .

When the array bounds problem described above is corrected and double_to_bits is passed a valid value, it should print the bits that encoded the value of the double . In most C implementations, this will be 0100000000100100000000000000000000000000000000000000000000000000, which is the encoding in the IEEE-754 binary64 format, also called double precision.

Also why does the & operand between arr[idx/CHAR_BIT] and (1u%CHAR_BIT) give 2 weird character symbols?

You have not shown the weird character symbols or other output, so we have no output to interpret.

The statement printf("array is : %s\\n", arr); prints arr as if it were a string containing printable characters, but it is used to contain “raw binary data,” so you should not expect that data to result in meaningful characters when printed. Remove that statement. Also, the fact that your program accessed vals out of bounds could cause other complications in output.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM