简体   繁体   中英

Why do these two files have different hex outputs?

I was going through K&R and decided to do an experiment. In K&R first the while loop is taught and then the for loop is taught. In doing so, the same program is written with both a while loop and for loop. These programs both have the same output and functionally do the same thing. I then thought to compare the two binary files using vim -d <(xxd celsius) <(xxd ccelsius) and thought that they would be the same file; however, they are not. While there are certain segment of the file that are the same there are significant differences as well. I was wondering why these differences exist and if there was any way to make the files compile to the same binary. I am using gcc as my compiler.

C Files

celsius.c

#include <stdio.h>

/* print Fahrenheit-Celsius table
 *  for fahr = 0, 20, ..., 300; floating-point version */
int main(void)
{
    float fahr, celsius;
    int lower, upper, step;

    lower = 0;  /* lower limit of temperature table */
    upper = 300;    /* upper limit */
    step = 20;  /* step size */

    fahr = lower;
    while (fahr <= upper) {
        celsius = (5.0/9.0) * (fahr-32.0);
        printf("%3.0f %6.1f\n", fahr, celsius);
        fahr = fahr + step;
    }
}

ccelcius.c

#include <stdio.h>

/* print Fahrenheit-Celsius table */
int main(void)
{
    float fahr;

    for (fahr = 0; fahr <= 300; fahr = fahr + 20)
        printf("%3.0f %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
}

Hex Diff File

diff <(xxd celsius) <(xxd ccelsius)

14,15c14,15
< 000000d0: c00e 0000 0100 0000 a700 0000 0000 0000  ................
< 000000e0: c00e 0000 0400 0000 0000 0000 0000 0000  ................
---
> 000000d0: e00e 0000 0100 0000 8d00 0000 0000 0000  ................
> 000000e0: e00e 0000 0400 0000 0000 0000 0000 0000  ................
19,20c19,20
< 00000120: 680f 0000 0100 0000 0600 0000 0000 0000  h...............
< 00000130: 680f 0000 0100 0000 0000 0000 0000 0000  h...............
---
> 00000120: 6e0f 0000 0100 0000 0600 0000 0000 0000  n...............
> 00000130: 6e0f 0000 0100 0000 0000 0000 0000 0000  n...............
24,25c24,25
< 00000170: 700f 0000 0100 0000 1a00 0000 0000 0000  p...............
< 00000180: 700f 0000 0200 0000 0000 0000 0000 0000  p...............
---
> 00000170: 740f 0000 0100 0000 1a00 0000 0000 0000  t...............
> 00000180: 740f 0000 0200 0000 0000 0000 0000 0000  t...............
29c29
< 000001c0: 900f 0000 0100 0000 0c00 0000 0000 0000  ................
---
> 000001c0: 900f 0000 0100 0000 1800 0000 0000 0000  ................
34,35c34,35
< 00000210: 9c0f 0000 0100 0000 0d00 0000 0000 0000  ................
< 00000220: 9c0f 0000 0000 0000 0000 0000 0000 0000  ................
---
> 00000210: a80f 0000 0100 0000 0b00 0000 0000 0000  ................
> 00000220: a80f 0000 0000 0000 0000 0000 0000 0000  ................
39,40c39,40
< 00000260: ac0f 0000 0100 0000 4800 0000 0000 0000  ........H.......
< 00000270: ac0f 0000 0200 0000 0000 0000 0000 0000  ................
---
> 00000260: b40f 0000 0100 0000 4800 0000 0000 0000  ........H.......
> 00000270: b40f 0000 0200 0000 0000 0000 0000 0000  ................
73c73
< 00000480: 1985 c866 b4a1 304e 965d 4a68 80be 0434  ...f..0N.]Jh...4
---
> 00000480: 37e9 3480 21a8 3e96 b783 ea6a 3feb 00d8  7.4.!.>....j?...
76c76
< 000004b0: 2800 0080 1800 0000 c00e 0000 0000 0000  (...............
---
> 000004b0: 2800 0080 1800 0000 e00e 0000 0000 0000  (...............
237,256c237,256
< 00000ec0: 5548 89e5 4883 ec20 c745 fc00 0000 00c7  UH..H.. .E......
< 00000ed0: 45f0 0000 0000 c745 ec2c 0100 00c7 45e8  E......E.,....E.
< 00000ee0: 1400 0000 f30f 2a45 f0f3 0f11 45f8 f30f  ......*E....E...
< 00000ef0: 1045 f8f3 0f2a 4dec 0f2e c80f 825d 0000  .E...*M......]..
< 00000f00: 0048 8d3d 9400 0000 f20f 1005 8000 0000  .H.=............
< 00000f10: f30f 100d 8000 0000 f30f 1055 f8f3 0f5c  ...........U...\
< 00000f20: d1f3 0f5a caf2 0f59 c1f2 0f5a c0f3 0f11  ...Z...Y...Z....
< 00000f30: 45f4 f30f 5a45 f8f3 0f5a 4df4 b002 e825  E...ZE...ZM....%
< 00000f40: 0000 00f3 0f10 45f8 f30f 2a4d e8f3 0f58  ......E...*M...X
< 00000f50: c1f3 0f11 45f8 8945 e4e9 90ff ffff 8b45  ....E..E.......E
< 00000f60: fc48 83c4 205d c390 ff25 a200 0000 0000  .H.. ]...%......
< 00000f70: 4c8d 1d91 0000 0041 53ff 2581 0000 0090  L......AS.%.....
< 00000f80: 6800 0000 00e9 e6ff ffff 0000 0000 0000  h...............
< 00000f90: 721c c771 1cc7 e13f 0000 0042 2533 2e30  r..q...?...B%3.0
< 00000fa0: 6620 2536 2e31 660a 0000 0000 0100 0000  f %6.1f.........
< 00000fb0: 1c00 0000 0000 0000 1c00 0000 0000 0000  ................
< 00000fc0: 1c00 0000 0200 0000 c00e 0000 3400 0000  ............4...
< 00000fd0: 3400 0000 680f 0000 0000 0000 3400 0000  4...h.......4...
< 00000fe0: 0300 0000 0c00 0100 1000 0100 0000 0000  ................
< 00000ff0: 0000 0001 0000 0000 0000 0000 0000 0000  ................
---
> 00000ec0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
> 00000ed0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
> 00000ee0: 5548 89e5 4883 ec20 0f57 c0c7 45fc 0000  UH..H.. .W..E...
> 00000ef0: 0000 f30f 1145 f8f3 0f10 0591 0000 000f  .....E..........
> 00000f00: 2e45 f80f 825b 0000 0048 8d3d 9800 0000  .E...[...H.=....
> 00000f10: f20f 1005 8800 0000 f30f 100d 7400 0000  ............t...
> 00000f20: f30f 5a55 f8f3 0f10 5df8 f30f 5cd9 f30f  ..ZU....]...\...
> 00000f30: 5acb f20f 59c1 f20f 1145 f00f 28c2 f20f  Z...Y....E..(...
> 00000f40: 104d f0b0 02e8 2400 0000 8945 ecf3 0f10  .M....$....E....
> 00000f50: 0543 0000 00f3 0f58 45f8 f30f 1145 f8e9  .C.....XE....E..
> 00000f60: 93ff ffff 8b45 fc48 83c4 205d c390 ff25  .....E.H.. ]...%
> 00000f70: 9c00 0000 4c8d 1d8d 0000 0041 53ff 257d  ....L......AS.%}
> 00000f80: 0000 0090 6800 0000 00e9 e6ff ffff 0000  ....h...........
> 00000f90: 0000 9643 0000 0042 0000 a041 0000 0000  ...C...B...A....
> 00000fa0: 721c c771 1cc7 e13f 2533 6420 2536 2e31  r..q...?%3d %6.1
> 00000fb0: 660a 0000 0100 0000 1c00 0000 0000 0000  f...............
> 00000fc0: 1c00 0000 0000 0000 1c00 0000 0200 0000  ................
> 00000fd0: e00e 0000 3400 0000 3400 0000 6e0f 0000  ....4...4...n...
> 00000fe0: 0000 0000 3400 0000 0300 0000 0c00 0100  ....4...........
> 00000ff0: 1000 0100 0000 0000 0000 0001 0000 0000  ................
258c258
< 00001010: 800f 0000 0100 0000 0000 0000 0000 0000  ................
---
> 00001010: 840f 0000 0100 0000 0000 0000 0000 0000  ................
518,519c518,519
< 00002050: 2502 0000 0003 00c0 1d00 0000 0000 0000  %...............
< 00002060: c01d 0000 0000 0000 0200 0000 0f01 1000  ................
---
> 00002050: 2502 0000 0003 00e0 1d00 0000 0000 0000  %...............
> 00002060: e01d 0000 0000 0000 0200 0000 0f01 1000  ................
521c521
< 00002080: c00e 0000 0100 0000 1c00 0000 0100 0001  ................
---
> 00002080: e00e 0000 0100 0000 1c00 0000 0100 0001  ................

In the first example

celsius = (5.0/9.0) * (fahr-32.0);

is using double to compute the result, and then truncating that to float , which is then promoted back to double to be printed with the %f format.

In the second example, again the calculation uses double

printf("%3.0f %6.1f\n", fahr, (5.0/9.0)*(fahr-32));

but there is no truncation to float , since a double is expected. So the computations have slightly different results.

If you do a diff of the disassembly, the results are pretty much identical when compiled with optimizations on, even if the binary doesn't exactly match (I've changed both source files to use floats exclusively because of Weather Vane's comments):

celsius.c

#include <stdio.h>

/* print Fahrenheit-Celsius table
 *  for fahr = 0, 20, ..., 300; floating-point version */
int main(void)
{
    float fahr, celsius;
    static const int lower = 0;
    static const int upper = 300;
    static const int step = 20;

    fahr = lower;
    while (fahr <= upper) {
        celsius = (5.0f/9.0f) * (fahr-32.0f);
        printf("%3.0f %6.1f\n", fahr, celsius);
        fahr = fahr + step;
    }
}

ccelsius.c

#include <stdio.h>

/* print Fahrenheit-Celsius table */
int main(void)
{
    float fahr;

    for (fahr = 0; fahr <= 300; fahr = fahr + 20)
        printf("%3.0f %6.1f\n", fahr, (5.0f/9.0f)*(fahr-32.0f));
}

To compile cc -Wall -O3 celsius.c -o celsius && cc -Wall -O3 ccelsius.c -o ccelsius

diff <(objdump -d celsius) <(objdump -d ccelsius)

2c2
< celsius:     file format elf64-x86-64
---
> ccelsius:     file format elf64-x86-64

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