Questions about C Function Prototypes and Compilation

后端 未结 4 1789
别那么骄傲
别那么骄傲 2020-12-19 11:37

With the following code:

int main(){
    printf(\"%f\\n\",multiply(2));
    return 0;
}

float multiply(float n){
    return n * 2;
}

When

相关标签:
4条回答
  • 2020-12-19 11:55

    Question1:

    So the invented prototype would be "int multiply(int)", and hence the errors. Is this correct?

    Not exactelly yes because it it depends of your Cx (C89, C90, C99,...)

    for function return values, prior to C99 it was explicitly specified that if no function declaration was visible the translator provided one. These implicit declarations defaulted to a return type of int

    Justification from C Standard (6.2.5 page 506)

    Prior to C90 there were no function prototypes. Developers expected to be able to interchange argu-ments that had signed and unsigned versions of the same integer type. Having to cast an argument, if the parameter type in the function definition had a different signedness, was seen as counter to C’s easy-going type-checking system and a little intrusive. The introduction of prototypes did not completely do away with the issue of interchangeability of arguments. The ellipsis notation specifies that nothing is known about the 1590 ellipsis supplies no information expected type of arguments. Similarly, for function return values, prior to C99 it was explicitly specified that if no function declaration was visible the translator provided one. These implicit declarations defaulted to a return type of int . If the actual function happened to return the type unsigned int , such a default declaration might have returned an unexpected result. A lot of developers had a casual attitude toward function declarations. The rest of us have to live with the consequences of the Committee not wanting to break all the source code they wrote. The interchangeability of function return values is now a moot point, because C99 requires that a function declaration be visible at the point of call (a default declaration is no longer provided)

    Question 2:

    How come when I break the code into 2 files it compiles?

    it will compile and it will be treated like indicated in the first question exactelly the same

    0 讨论(0)
  • 2020-12-19 11:58

    An unspecified function has a return type of int (that's why you get the warning, the compiler thinks it returns an integer) and an unknown number of unspecified arguments.

    If you break up your project in multiple files, just declare a function prototype before you call the functions from the other files, and all will work fine.

    0 讨论(0)
  • 2020-12-19 11:59

    Question 1: Yes you are correct. If there is no function prototype, the default type is int

    Question 2: When you are compiling this code as one file, the compiler see that there is already function named multiply and it has a different type than supposed (double instead of int). Thus compilation doesn't work.

    When you separate this in two files, the compiler makes two .o files. In the first one it suppose that the multiply() function will be in other file. Then linker links both files into a binary and according to the name multiply inserts call of float multiply() on the place of int multiply() supposed by the compiler in the first .o file.

    Question 3: If you read int 2 as a float, you will get a very small number (~1/2^25), so after that you multiply it by 2 and it still remains too small for format %f. That's why you see 0.00000.

    0 讨论(0)
  • 2020-12-19 12:12

    So the invented prototype would be "int multiply(int)", and hence the errors. Is this correct?

    Absolutely. This is done for backward compatibility with pre-ANSI C that lacked function prototypes, and everything declared without a type was implicitly int. The compiler compiles your main, creates an implicit definition of int multiply(int), but when it finds the real definition, it discovers the lie, and tells you about it.

    How come when I break the code into 2 files it compiles?

    The compiler never discovers the lie about the prototype, because it compiles one file at a time: it assumes that multiply takes an int, and returns an int in your main, and does not find any contradictions in multiply.c. Running this program produces undefined behavior, though.

    Once I run the program above (the version split into 2 files) the result is that 0.0000 is printed on the screen.

    That's the result of undefined behavior described above. The program will compile and link, but because the compiler thinks that multiply takes an int, it would never convert 2 to 2.0F, and multiply will never find out. Similarly, the incorrect value computed by doubling an int reinterpreted as a float inside your multiply function will be treated as an int again.

    0 讨论(0)
提交回复
热议问题