Home > OS >  Why doesn't linking a function of the wrong type return garbage?
Why doesn't linking a function of the wrong type return garbage?

Time:12-26

I'm going through the K&R C book and chapter 4.2 says the following:

If atof itself and the call to it in main have inconsistent types in the same source file, the error will be detected by the compiler. But if (as is more likely) atof were compiled separately, the mismatch would not be detected, atof would return a double that main would treat as an int, and meaningless answers would result.

I wanted to see for myself what would happen if I created and inconsistently used a function as they describe:

main.c:

#include <stdio.h>

int floatFunction();

int main() {
    int result = floatFunction();
    printf("result: %d\n", result);
}

floatFunction.c:

float floatFunction() {
    return 10;
}

bash:

$ gcc main.c floatFunction.c -o main
$ ./main
result: 0
$

Regardless of what value I had floatFunction return, I always got 0 as a result. I also tried compiling with -o3, same result. I was expecting to see the bit pattern of 10.0 interpreted as an int as a result. Why is this not happening?

Also, why doesn't the compilation process notify me that the types don't match and how can I protect myself from making a mistake like this in real code?

CodePudding user response:

There are different registers used for passing (and returning) floating-point vs. integral values (pointers and integers) on x86 at least.

Why you consistently had integral zero in the return-register for integral values, while the return-register for floating-point values was used for the true return-value, I don't know. Just luck probably.

See for example What are the calling conventions for UNIX & Linux system calls (and user-space functions) on i386 and x86-64 for more about Linux calling conventions.

Anyway, remember that whatever you observe, at least on the language level it is simply undefined behavior, anything goes.

CodePudding user response:

I was expecting to see the bit pattern of 10.0 interpreted as an int as a result. Why is this not happening?

The most likely reason is that on your platform (which you didn't specify) floating point values are returned in a different register from the one in which integer values are returned.

For example, on x86_64 the integer result is returned in the rax register, while double and float result is returned in the xmm0 register.

Here is an article on various x86 calling conventions.

If you are not on x86_64, you'll need to look up the calling conventions for your platform.

Also, why doesn't the compilation process notify me that the types don't match

The compilation process only sees one source file (compilation unit) at at time, so it can't warn you.

The linker could, but only the AIX linker actually does (of the ones I know).

how can I protect myself from making a mistake like this in real code?

By declaring your functions in a header file and including that header in both compilation units.

  •  Tags:  
  • c gcc
  • Related