4

I have a C file (say file1.c) that calls a function fun1(1,b).

This function fun1(int a,int b) resides in another C file (say file2.c) but its prototype is not included in the header file (say file2.h). file2.h is included in file1.c.

My question is, if I call fun1(a,b) from file1.c, will it work by passing control to the function definition in file2.c? Or will an exception occur or what will be the expected behavior?

Do I have to give a prototype of fun1(int a, int b) in file2.h for this to work?

sth
  • 222,467
  • 53
  • 283
  • 367
Wilma
  • 51
  • 1
  • 1
  • 4

2 Answers2

5

A couple things can happen depending on the situation and your compiler:

  • You get a compilation error. The compiler throws up its arms and refuses to produce an object file.
  • The compiler treats the function declaration as implied by the call and proceeds to link. It may assume that you know what you're doing in terms of function arguments. Usually it also assumes an int return type. Almost every compiler I've worked with will produce a warning when it does this.
  • The compiler treats the declaration as implied by the call but fails to link. Like the above, but the linker then notices that the implied function you're trying to call and the one you actually did write are different and dies.

You SHOULD provide a prototype regardless.

bearda
  • 301
  • 1
  • 8
  • 1
    Declaration of prototypes and inclusions of header files have nothing to do with the link stage of generating the binary. Any C compiler will simply throw out a warning AT most. The time where you WILL get a warning, say using gcc is if you have missing-prototypes warning flag on and even then it is only raised for global functions and only for the source file that implements the function and has no formal prototype present. ANSI C specifically allows calling functions without prototypes present. – Ahmed Masud Oct 26 '11 at 16:41
  • 1
    @Ahmed I agree with you that it's not directly related, but my point is that by not providing a prototype to the compiler you remove one level of checking. If you had a mismatch with a prototype the compiler would give you an error. If you don't have a prototype then it falls to the linker to catch the error. You *want* the compiler to catch the error, so give it a prototype so it can do it's job. – bearda Oct 28 '11 at 15:42
3

Expected behaviour is that your functions will get called, provided the object files are linked together. Any undeclared function, is assumed to be an external function that returns an integer for compile purpose, and an external symbol (to the object file) for purposes of linking. I'll give you concrete example:

foo.c:

void foo(const char *name) {
    printf("foo called with %s\n", name);
}

bar.c:

void bar(int a) {
    printf("bar called with %d\n", a);
}

main.c:

int main(int argc, char *argv[]) {
    foo("Hello");
    bar(5);
    return 0;
}

Compiling the object files using gcc:

gcc -fno-builtin -ansi -c -o foo.o foo.c
gcc -fno-builtin -ansi -c -o bar.o bar.c
gcc -fno-builtin -ansi -c -o main.o main.c

These should not produce any warnings or errors

Now link them together:

gcc -o progy main.o bar.o foo.o 

Note that i used gcc to link the binaries, but that is equivalent of:

ld -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o progy  /usr/lib64/crt1.o /usr/lib64/crti.o /usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.1/crtbegin.o main.o foo.o bar.o -lc  -L/usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.1 -lgcc -lgcc_s /usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.1/crtend.o /usr/lib64/crtn.o

on my Linux 64-bit platform. (GCC actually runs LD like this to do the linking)

Using your C compiler (in my case gcc) for linking will ensure that linker is called correctly for whatever your build target platform is. If you use an IDE then these steps are all hidden by a nice interface.

sth
  • 222,467
  • 53
  • 283
  • 367
Ahmed Masud
  • 21,655
  • 3
  • 33
  • 58
  • Your code sample causes undefined behaviour in C89 because calling the function without a prototype in scope causes an implicit declaration with return type `int`; however the function actually returns `void`. In C99 and C11 it is ill-formed. – M.M Aug 28 '15 at 00:32