3

My programming environment is gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)

I code like:

#include <stdio.h>

typedef unsigned char *byte_pointer;

void show_bytes(byte_pointer start, int len){
  int i;
  for (i = 0; i<len; i++)
    printf(" %.2x", start[i]);
  printf("\n");
}

void show_float(float x){
  show_bytes((byte_pointer)&x, sizeof(float));
}

int main(){
  int y = 0xffffff;
  float f = y;
  show_float(f);
  return 0;
}

and the machine give the result: 00 00 00 e0

I think it is not right according to IEEE 754; but i don't know why. while the same code in VS 2013 in windows give the right answer: ff ff 7f 4b

Does gcc 5.4.0 not adopt the IEEE 754? Or are there some problem in my code?

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
HannanKan
  • 163
  • 2
  • 14
  • 6
    Don't `typedef` pointers for fun; that way lies madness.... – ad absurdum Aug 03 '17 at 13:39
  • 3
    This code outputs `ff ff 7f 4b` for me with gcc 4.9.4 – ad absurdum Aug 03 '17 at 13:44
  • 1
    I got the same output (`ff ff 7f 4b`) using mingw-64 7.1.0 on windows. If you really have run the same exact code it seems it must use a different representation. I would recommend trying some other numbers to see how they compare as well – rtpax Aug 03 '17 at 13:58
  • Is your machine little endian or big endian? (you can check with macros `#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__`) – rtpax Aug 03 '17 at 14:07
  • 1
    Just pasted your code to https://godbolt.org/g/cZGBuA, with gcc 5.4. In the assembly of main it clearly loads 0x4b7fffff with -O2. With -O1 the constant is emitted somewhere and referenced. If the encoding were different, the hardware instructions would not work, assuming that those work with IEEE754 – PaulR Aug 03 '17 at 14:42
  • Note that 00 00 00 e0 --> -36893488147419103232.0 --> 0xCCCCCCCCCCCCCCCD – chux - Reinstate Monica Aug 03 '17 at 18:50

2 Answers2

5

Does gcc 5.4.0 not adopt the IEEE 754?
Or are there some problem in my code?

gcc 5.4.0 and IEEE 754 is not the issue. Certainly the code is not conforming


By re-ordering the functions, yet same code, I get 2 warnings and can replicate OP's output 00 00 00 e0

warning: implicit declaration of function 'show_float' [-Wimplicit-function-declaration]
warning: conflicting types for 'show_float'

I suspect OP has not posted true code. - or its not all in one file. The real code has the usually problem of code passing double - due to lack of a prior declaration/definitioon, yet show_float() expects a float.

#include <stdio.h>

typedef unsigned char *byte_pointer;

void show_bytes(byte_pointer start, int len){
  int i;
  for (i = 0; i<len; i++)
    printf(" %.2x", start[i]);
  printf("\n");
}

int main(){
  int y = 0xffffff;
  float f = y;
  show_float(f);  // code lacks proto-type, so assumes it needs to pass a double
  return 0;
}

void show_float(float x){
  show_bytes((byte_pointer)&x, sizeof(float));
}

Fix by declaring prototypes or re-order code.

#include <stdio.h>

typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, int len);
void show_float(float x);

/* the 3 functions in any order */
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • you are right! I am not put all the code in one file. I put main function in main.c and put the typedef clause, show_bytes function and show_float function all in show_bytes.c. However, I use command line 'gcc main.c show_bytes.c -o main' and 'gcc show_bytes.c main.c -o main' and run ./ main – HannanKan Aug 04 '17 at 01:57
  • @HannanKan That is one of the values of .h files. Put `typedef unsigned char *byte_pointer; void show_bytes(byte_pointer start, int len); void show_float(float x);` in a .h file and include that in each .c file. – chux - Reinstate Monica Aug 04 '17 at 01:59
  • you are right! I am not put all the code in one file. I put main function in main.c and put the typedef clause, show_bytes function and show_float function all in show_bytes.c. However, I use command line 'gcc main.c show_bytes.c -o main' and 'gcc show_bytes.c main.c -o main' and run ./main . And the results are the same--00 00 00 e0. Theoretically, I compile them together, therefore function used in main should find where it is defined and call correctly. Facts show that function call can be conducted, while it gets wrong answer. I have no idea what's wrong. – HannanKan Aug 04 '17 at 02:04
  • 1
    @HannanKan "Theoretically, I compile them together, therefore function used in main should find where it is defined and call correctly" --> no, Use the suggested prototypes. – chux - Reinstate Monica Aug 04 '17 at 02:30
  • 4
    @chux: Goes to show again **how important it is that people post their real code**, not something that very much looks like it. The problem was caused by lacking prototypes. This could not be seen in the code that was posted. Great detective work! – Rudy Velthuis Aug 04 '17 at 06:23
0

gcc does not use a different single floating point representation, but rather promotes it to a double somewhere in the program. The conversion probably happens at the call to show_bytes, but it could be somewhere else. If you change the floats to doubles you can get the same wrong output again, it will probably work using both compilers.

This may be a bug or an optimization by gcc, but it is not normal behavior for c compilers, see this question

#include <stdio.h>

typedef unsigned char *byte_pointer;

void show_bytes(byte_pointer start, int len) {
    int i;
    for (i = 0; i<len; i++)
        printf(" %.2x", start[i]);
    printf("\n");
}

void show_float(double x) {
    show_bytes((byte_pointer)&x, sizeof(float));
}

int main() {
    int y = 0xffffff;
    double f = y;
    show_float(f);
    return 0;
}

This outputs

00 00 00 e0

if you change sizeof(float) to sizeof(double) in your program that outputs incorrectly, you will be able to see the entire double to verify this

for me using doubles I get

00 00 00 e0 ff ff 6f 41
rtpax
  • 1,687
  • 1
  • 18
  • 32
  • 1
    Interesting explanation, but if there is an implicit promotion to double in the original program, that's a compiler bug. As far as I can see, the program should dump the four bytes in the `float`, as intended. – Florian Weimer Aug 03 '17 at 14:52
  • @FlorianWeimer I agree, I am thinking bug as well, though I doubt c standard prohibits this behavior. Until OP tries the code can't say for sure. – rtpax Aug 03 '17 at 14:56