0
votes

i have a project That includes three files in codeblocks :

main.c :

#include <stdio.h>
#include <conio.h>

int global = 10;

void f1(int);
void f1_1(int);
void f2(void);

int main()
{
    int x = 5;
    printf("inside main file");
    getch();
    f1(x);
    f2();
    getch();
    return 0;
}

file1.c :

#include <stdio.h>
#include <conio.h>

void f1(int x)
{
    printf("\ninside file1 >> f1 and x = %i", x);
    getch();
    f1_1(x);
}

void f1_1(int x)
{
    printf("\ninside file1 >> f1 >> f1_1 and x = %i", x);
    getch();
}

file2.c :

#include <stdio.h>
#include <conio.h>

extern int global;

void f2()
{
    printf("\ninside file2 >> f2 function , global var = %i", global);
    getch();
}

when i compiled it , i got these warnings :

c|8|warning: implicit declaration of function 'f1_1'; did you mean 'f1'? [-Wimplicit-function-declaration]

c|11|warning: conflicting types for 'f1_1'

what should i do for this ?

2
Ideal way: move the function prototypes to different .h file and include it wherever it is required, otherwise define f1_1 before f1. - kiran Biradar
Note that there is a very large difference between C and C++ in a situation like this: In C++ you would not get a warning but an error. In the future, please only tag the actual programming language you're working with. - Some programmer dude

2 Answers

2
votes
void f1(int);
void f1_1(int);
void f2(void);

Should be:

extern void f1(int);
extern void f1_1(int);
extern void f2(void);

Or, as @kiranBiradar points out, you can declare them in header files

file1.h

#pragma once
extern void f1(int);
extern void f1_1(int);

file2.h

#pragma once
extern void f2(void);


Note the use of the extern keyword. When you forward declare a function in a file as void f(void), the symbol 'f' is public, meaning other compilation units can reference it. When you declare it as extern void f(void), then the compiler doesn't expect the function to be defined in that compilation unit and leaves it up to the linker to find that symbol.

2
votes

This is the perfect time to learn about the important concept of translation units.

Each single source file, with all included header file, forms a single translation unit. Each translation unit is separate and distinct and compiled stand-alone without any knowledge of other translation units.

That means symbols declared in e.g. the main.c source file will not be known in the file1.c source file.

When you compile file1.c the compiler simply doesn't know about the f1_1 function declaration you have in the main.c source file, so you get a warning about that fact.

To solve your problem, you need to declare the f1_1 function in the file1.c file. Either by adding a forward declaration (like the one you have in main.c), or moving the whole function definition (implementation) of f1_1 above the f1 function.

Or you could create a single header file which contains all the declarations needed (for the f1, f1_1, f2 function, plus the global external variable declaration), and include this single header file in all your source files. This solution works best if you have multiple symbols (functions, variables, etc.) that are used in multiple translation units.

My personal recommendation is this: Since the f1_1 function is only used internally inside the file1.c source file, move its definition above f1, and make it static. Then remove its declaration from the main.c source file.


Regarding the "implicit declaration" and "conflicting types" warnings, it's because in older standards of C it was allowed to not declare functions and the compiler would create an implicit declaration by guessing the declaration based on the first call of the function.

The important part about the guessing is that only the arguments were guessed, the return type would always be int.

I don't know the exact wording in the specifications about this since it was removed in the C99 specification, but most compilers still allow this with only emitting a warning instead of an error. This is where the first warning comes from.

However, the return type of int is still being used. And since your f1_1 function is declared to return void later in the file1.c source file, there's a mismatch between the guessed declaration (int f1_1(int)) and the actual declaration (void f1_1(int)) which leads to the second warning.