0

I am creating a program for homework, and the goal is trying to teach us how a union works conceptually. I believe I understand this concept, but I am having difficulty with one of my outputs; Long Double as Hex.

I am under the assumption anything long needs a capital L after the percent sign when printing. For example to print a long double float:

printf("\nLong double: %Lf\n", value.ld);

Similarly, if I wanted to print a Long Double float in hex I would use:

printf("\nLong double: %Lx", value.ld);

My professor's output is as follows:

Professors Output long double 22fde0

My Output is as follows:

My Output long double 62fe40

The differences are in the printed value for Long Double in hex. Is this a value that might be different from computer to computer or am I making a mistake in my thinking.

My code

#include <stdio.h>

// define union data
    union data {
        float f;
        double d;
        long double ld;
    }value; //union variable

// begin main function
int main(void){

    // get initial user input
    printf("Enter data for type float: ");
    scanf(" %f", &value.f);

    puts("\nBreakdown of the element in the union: ");
    printf("Float: %f", value.f);
    printf("\nDouble: %f", value.d);
    printf("\nLong double: %Lf\n", value.ld);

    puts("\nBreakdown in hex: ");
    printf("Float: %x", value.f);
    printf("\nDouble: %x", value.d);
    printf("\nLong double: %Lx", value.ld);

    // get user input
    printf("\n\nEnter data for type double: ");
    scanf(" %lf", &value.d);

    puts("\nBreakdown of the element in the union: ");
    printf("Float: %f", value.f);
    printf("\nDouble: %f", value.d);
    printf("\nLong double: %Lf\n", value.ld);

    puts("\nBreakdown in hex: ");
    printf("Float: %x", value.f);
    printf("\nDouble: %x", value.d);
    printf("\nLong double: %Lx", value.ld);

    // get user input
    printf("\n\nEnter data for type long double: ");
    scanf(" %lf", &value.ld);

    puts("\nBreakdown of the element in the union: ");
    printf("Float: %f", value.f);
    printf("\nDouble: %f", value.d);
    printf("\nLong double: %Lf\n", value.ld);

    puts("\nBreakdown in hex: ");
    printf("Float: %x", value.f);
    printf("\nDouble: %x", value.d);
    printf("\nLong double: %Lx", value.ld);

    return 0;
} // end main function
Arthur Green
  • 136
  • 1
  • 10
  • Do you really think that an union can **convert** an object representation? In your case it seems that you expect that setting the float object of the `union data` magically give you the same value expressed in `double` or `long double` format at your desire? – Frankie_C Nov 03 '18 at 17:09
  • @Frankie_C don't believe it should be the same, that is the point of this assignment. Whichever value we store into the union last is what is held inside of it. – Arthur Green Nov 03 '18 at 17:12
  • "Whichever value we store into the union last is what is held inside of it" this is correct. So what should be the sense assigning a float and dumping the hex content of the long double? Also printing a double or a long double from a float init value is nosense... – Frankie_C Nov 03 '18 at 17:25
  • @Frankie_C to show that the output isn't correct for anything other than what we've just scanned in. Are you saying our outputs are different because the value is no good to begin with? – Arthur Green Nov 03 '18 at 17:29
  • @Frankie_C thanks I think I understand. I appreciate your help – Arthur Green Nov 03 '18 at 17:32
  • No, simply that this is a very strange exercise. Really make no sense. There is no direct way to print the hex contents of different types, that obviously have different sizes. Maybe your teacher mean to print the hex content of the whole union? Or he use the `long double` because it's the largest type and for this reason should include all bytes? – Frankie_C Nov 03 '18 at 17:32
  • Here is the full question if you are interested.. https://imgur.com/a/s5p694L I am sad to say I didn't see the Note: earlier, but I appreciate the discussion with programmers with experience. – Arthur Green Nov 03 '18 at 17:35
  • There is no reference to the "hex breakdown" reported in the question paper. Still really doesn't make any sense. The hex values reported doesn't seems to be IEEE representation, float, double or long double of 234.567. In any case there is no reference in the question about those hex values. You should ask to your teacher what he meant. – Frankie_C Nov 03 '18 at 17:47
  • You can use this link https://www.h-schmidt.net/FloatConverter/IEEE754.html, or this http://weitz.de/ieee/, to exercise floating point memory representation for some understanding. Ah I was forgetting to say that the hex representation isn't even a hex-floating representation (the one you get using the `%a` formatter in `printf`). – Frankie_C Nov 03 '18 at 17:53

3 Answers3

1

The %x format specifier is expecting an integer type to be printed in hex. Passing in a floating point type for this invokes undefined behavior.

You can print floating point numbers in hex with the %a format specifier:

printf("\nLong double: %La", value.ld);
dbush
  • 205,898
  • 23
  • 218
  • 273
1

Is this a value that might be different from computer to computer

Definitely. It's not at all clear what your professor meant by "long double as hex". If you do as you've done, passing a long double to the %x specifier, then you get undefined behaviour - the %x specifier expects an integer (or variant) and it's not easy to predict what will happen if you pass it a float (or variant).

If you use the %a specifier, which is explicitly for printing floats in hex, then you get a hex representation of the floating point value, not the contents of memory. So, for example 1.5 would be printed as 0x1.8p+0 because .8 is hexadecimal for .5 in decimal.

If what you really want is the contents of memory, as hex, then you need to pass the %x specifier an integer. Easiest way to do that is add appropriate integer types to your union.

union data {
        float f;
        int i;
        double d;
        long int li;
        long double ld;
        long long int lli;
    }value; //union variable

Then, if you want the memory contents in hex of a double, for example, just use:

// get user input
printf("\n\nEnter data for type double: ");
scanf(" %f", &value.d);

puts("\nBreakdown of the element in the union: ");
printf("Double: %f", value.d);
printf("Hex: %lx", value.li);

By the way, %l... (lowercase ell) is for integers, %L... (uppercase ell) is for float types. A long int is typically the same size as a double on 64 bit platforms (but not guaranteed to be so!). %f, somewhat confusingly, is for a double argument. There is no specifier for floats - they are automatically promoted to doubles.

Heath Raftery
  • 3,643
  • 17
  • 34
0

Please use union, as pointed in how to print float in hex format in C?

Here is what I grabbed from the link:

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <math.h>

int main (void) {

    float pi = (float)M_PI;
    union {
        float f;
        uint32_t u;
    } f2u = { .f = pi };

    printf ("pi (floating point): %f\n", pi);
    printf ("pi (hex representation): 0x%\n", f2u.u);

    return 0;
}

Output:

$ ./bin/float_hex
pi (floating point) : 3.141593
pi (hex representation): 0x40490fdb
duong_dajgja
  • 4,196
  • 1
  • 38
  • 65
  • I am sorry but I have reviewed this post before making my own and my question is not answered by that thread. If I used %a or %La the hexadecimal output is 0x0.000000p-1022 which is very far from my professors of 22fde0 – Arthur Green Nov 03 '18 at 17:02
  • Maybe my professor is wrong as the more I research this the more I believe the output should be in the format of 0x0.000000p-1022 – Arthur Green Nov 03 '18 at 17:05
  • This answer does NOT use `%a`. It prints the hexa format of the four-byte representing the float - that is `0x40490fdb` for the pi of `3.141593`. – duong_dajgja Nov 04 '18 at 09:26