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?
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.
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.
Related
I'm a beginner learning c. I know that use of word "static" makes a c function and variable local to the source file it's declared in. But consider the following...
test.h
static int n = 2;
static void f(){
printf("%d", n);
}
main.c
#include <stdio.h>
#include "test.h"
int main()
{
printf("%d", n);
f();
return 0;
}
My expected result was that an error message will throw up, since the function f and variable n is local to test.h only? Thanks.
But instead, the output was
2
2
EDIT:
If it only works for a compilation unit, what does that mean? And how do I use static the way I intended to?
static makes your function/variable local to the compilation unit, ie the whole set of source code that is read when you compile a single .c file.
#includeing a .h file is a bit like copy/paste-ing the content of this header file in your .c file. Thus, n and f in your example are considered local to your main.c compilation unit.
Example
module.h
#ifndef MODULE_H
#define MODULE_H
int fnct(void);
#endif /* MODULE_H */
module.c
#include "module.h"
static
int
detail(void)
{
return 2;
}
int
fnct(void)
{
return 3+detail();
}
main.c
#include <stdio.h>
#include "module.h"
int
main(void)
{
printf("fnct() gives %d\n", fnct());
/* printf("detail() gives %d\n", detail()); */
/* detail cannot be called because:
. it was not declared
(rejected at compilation, or at least a warning)
. even if it were, it is static to the module.c compilation unit
(rejected at link)
*/
return 0;
}
build (compile each .c then link)
gcc -c module.c
gcc -c main.c
gcc -o prog module.o main.o
You have included test.h in main.c.
Therefore static int n and static void f() will be visible inside main.c also.
When a variable or function is declared at file scope (not inside any other { } brace pair), and they are declared static, they are local to the translation unit they reside in.
Translation unit is a formal term in C and it's slightly different from a file. A translation unit is a single c file and all the h files it includes.
So in your case, the static variable is local to the translation unit consisting of test.h and main.c. You will be able to access it in main.c, but not in foo.c.
Meaning that if you have another .c file including test.h, you'll get two instances of the same variable, with the same name. That in turn can lead to all manner of crazy bugs.
This is one of many reasons why we never define variables inside header files.
(To avoid spaghetti program design, we should not declare variables in headers either, unless they are const qualified.)
As I was going through a huge source code, I came across some files where there is only one function declared in, let's say, "code.h" but in "code.c" there are many functions declared and defined.
What is the exact use of declaring and defining functions in .c files ?
How can we access one of those functions in a source file from other source file ?
It would be helpful if anyone can provide an example. Thanks
Splitting a complex routine in multiple smaller routines might make the code easier to understand and also would allow you to follow the single responsibility principle (What is an example of the Single Responsibility Principle?). By declaring and defining them only in a .c file (and declaring them static), you can hide the internal details from users.
If you, for instance, create a library, then your header could only show the public functions you'd like your users to use.
So only put your functions in a header if you'd like those functions available to anyone who includes the header.
If you'd like to keep a function internal to your .c file, seriously consider adding the static keyword as well: what is the advantage of static function?
---edit---
How can we access one of those functions in a source file from other source file ?
If the function isn't static, you could technically declare it anywhere* you'd like and use it there as well. Though, by the above argument, this would be bad practice.
Example:
a.c
int secret_a(int x)
{
return x+1;
}
main.c
#include <stdio.h>
//access a secret function from a.c
int secret_a(int);
int main()
{
printf("secret_a(3) gives: %d\n", secret_a(3));
return 0;
}
(*) anywhere allowed by the C language
How can we access one of those functions in a source file from other source file ?
That is the whole idea with defining some functions in the header, and some only in the c-file.
The functions defined in the header, can be called by other source files.
The functions only defined in the source file, can be hidden - it is a usual practice to mark functions, only declared in a source file, as static.
That makes their visibility limited to the file-scope (only code inside the same file can 'see' the functions).
The reason why this is done is to split the code into a more cleaner and sorted format so that functions concerning a particular operation can be grouped together in to one file and then called from other file. NOTE: this is not mandatory to do but a good programming practice.
Now there are two ways to do it :
1. including the files
2. Declaring the function as extern and then linking them at linking time.
1.
Including the file is the method that you are probably seeing in your code at hand. Functions are defined in one file and that file is included using #include"filename.[h/c]" and then calling the function as it were declared in the given file.
file_to_include.c
void my_func()
{
printf("Hello!\n");
}
file_that_include.c
#include<stdio.h>
#include"file_to_include.c"
int main()
{
my_func();
return 0;
}
to compile you just do
gcc file_that_include.c
using extern you can do the same but with out using the #include directive
file_to_include.c
void my_func()
{
printf("Hello!\n");
}
file_that_include.c
#include<stdio.h>
extern void my_func();
int main()
{
my_func();
return 0;
}
In this case while compiling you need to provide both files to the compiler
gcc file_that_include.c file_to_include.c
I would suggest reading up on the "extern" keyword.
From what I can understand in your question you have two files - "code.h" and "code.c". However, "code.h" only declares certain functions in "code.c":
code.h
int func1();
int func2();
code.c
int func1()
{
return 1;
}
int func2()
{
return 2;
}
int func3()
{
return 3;
}
main.c
#include "stdio.h"
#include "code.h"
extern int func3();
int main()
{
printf("%d ", func1());
printf("%d ", func2());
printf("%d ", func3());
}
Compiling using gcc:
gcc main.c code.c
yields:
main.c: In function ‘main’:
main.c:10:17: warning: implicit declaration of function ‘func3’ [-Wimplicit-function-declaration]
printf("%d ", func3());
and when executed:
1 2 3
The "extern" keyword basically tells the compiler "there is a definition for a function with this declaration" for compiling. During linking the linker will find the definition, and link to it.
This is however a clumsy way of doing it, since the caller ("main.c") needs to know what is going on in "code.c", and continually add more extern declaration, etc. etc.
So rather include functions you which to have global scope in "code.h". If there are functions in "code.c" which od not have global scope, consider making them "static".
Some more reading:
Effects of the extern keyword on C functions
I'm getting an error when I compile my main.c
The error says:
functions.c:27:6: warning: conflicting types for 'secondfunction' [enabled by default]
functions.c:23:2: note previous implicit declaration of 'secondfunction' was here
(My program has a file called main.c, header.h, and functions.c)
main.c:
#include "header.h" /*Includes the header file*/
int main(void) /*Starts the main function.*/
{
course();
firstfunction(filename,fileextension,fp,MAX_SIZE);
/*
thirdfunction();
fourthfunction();
fifthfunction();
sixthfunction();
*/
return 0;
} /*Ends the main function.*/
header.h:
#include <stdio.h>
#include <string.h>
#include "functions.c"
#define MAX_SIZE 50
struct records
{
double euid;
char firstname[MAX_SIZE];
char lastname[MAX_SIZE];
float gpa;
};
void course(void);
void firstfunction(char filename[],char fileextension[],FILE* fp,int SIZE);
void secondfunction(FILE* fp);
struct records people;
FILE* fp;
char filename[MAX_SIZE],fileextension[MAX_SIZE];
functions.c:
void course(void)
{
printf("\n\n\n\n\nDepartment: CSCE\nCourse number: 1030\nProgram number: Homework 3\nName: xxxxxxxxxxxxxx\nEUID: xxxxxxxxxxxxx\nEmail: xxxxxxxxx\n\n\n\n\n");
}
void firstfunction(char filename[],char fileextension[],FILE* fp,int SIZE)
{
printf("Please enter the file name (ex:filename)\n"); /*Asks for the name and the extension*/
scanf("%s",filename);
printf("Please enter the file extension (ex:.txt)\n");
scanf("%s",fileextension);
strcat(filename,fileextension); /*Puts them together with strcat*/
printf("%s\n",filename);
fp=fopen(filename,"r");
secondfunction(fp);
fclose(fp);
} /*End of the first function*/
void secondfunction(FILE* fp)
{
} /*End of the second function.*/
Thanks for the help guys!!
I don't think it's the variables being passed to the function I think it's the fact that I'm calling a function from within a function. How do I fix this?
remove this line #include "functions.c" from header.h and include header.h in functions.c
You make use of secondfunction() in functions.c before you declare or define this function.
So compiler treats her as it usually does with unknown functions: assumes it takes variable number of int arguments and returns int.
When it next finds your definition - it yells about differences because your function returns void and takes FILE* as an argument.
Move your secondfunction() definition before firstfunction() and it will work. But what you should really do is read on what to put in header files. In your case put all functions declarations in header file, and problem will be gone, if you include header file on top of your functions.c
You declare both functions in header.h, which is great.
But in functions.c, when you call secondfunction from within firstfunction, no declaration or definition of secondfunction is yet visible.
You should add
#include "header.h"
to the top of functions.c. You should also add include guards to header.h so that you don't run into problems if it's included more than once:
#ifndef H_HEADER
#define H_HEADER
/* contents of header.h */
#endif
And as Mario's answer points out, you shouldn't include functions.c from anywhere. Except in unusual cases, only .h files should be #included.
Each function should be declared in a .h file, and defined in a .c file.
Each file that needs to refer to a given function should have a #include directive for the header that declares it.
(main needn't be declared in a header, since it's not normally called.)
As for the confusing "conflicting types" message, that's because of an obsolescent feature of C. In older versions of the language (prior to the 1999 standard), a call to an undeclared function would result in an implicit declaration of that function, and the compiler would assume that it returns a result of type int. Even if you're using a compiler that still does this (many still do by default), you should ensure that each function you call has a visible declaration.
I am currently working on my first "serious" C project, a 16-bit vm. When I split up the files form one big source file into multiple source files, the linker (whether invoked through clang, gcc, cc, or ld) spits out a the error:
ld: duplicate symbol _registers in register.o and main.o for inferred
architecture x86_64
There is no declaration of registers anywhere in the main file. It is a uint16_t array if that helps. I am on Mac OS 10.7.3 using the built in compilers (not GNU gcc). Any help?
It sounds like you've defined a variable in a header then included that in two different source files.
First you have to understand the distinction between declaring something (declaring that it exists somewhere) and defining it (actually creating it). Let's say you have the following files:
header.h:
void printIt(void); // a declaration.
int xyzzy; // a definition.
main.c:
#include "header.h"
int main (void) {
xyzzy = 42;
printIt();
return 0;
}
other.c:
#include <stdio.h>
#include "header.h"
void printIt (void) { // a definition.
printf ("%d\n", xyzzy);
}
When you compile the C programs, each of the resultant object files will get a variable called xyzzy since you effectively defined it in both by including the header. That means when the linker tries to combine the two objects, it runs into a problem with multiple definitions.
The solution is to declare things in header files and define them in C files, such as with:
header.h:
void printIt(void); // a declaration.
extern int xyzzy; // a declaration.
main.c:
#include "header.h"
int xyzzy; // a definition.
int main (void) {
xyzzy = 42;
printIt();
return 0;
}
other.c:
#include <stdio.h>
#include "header.h"
void printIt (void) { // a definition.
printf ("%d\n", xyzzy);
}
That way, other.c knows that xyzzy exists, but only main.c creates it.
I declared a variable i in temp2.h
extern i; which contains just one above line
and made another file
temp3.c
#include<stdio.h>
#include<temp2.h>
int main ()
{
extern i;
i=6;
printf("The i is %d",i);
}
When I compiled above as
cc -I ./ temp3.c I got following errors
/tmp/ccJcwZyy.o: In function `main':
temp3.c:(.text+0x6): undefined reference to `i'
temp3.c:(.text+0x10): undefined reference to `i'
collect2: ld returned 1 exit status
I had declared extern in temp3.c above as K R page 33 says as I mentioned in above post.
I tried another way for temp3.c with same header file temp2.h
#include<stdio.h>
#include<temp2.h>
int main ()
{
i=6;
printf("The i is %d",i);
}
and compiled it cc -I ./ temp3.c and got following error
/tmp/ccZZyGsL.o: In function `main':
temp3.c:(.text+0x6): undefined reference to `i'
temp3.c:(.text+0x10): undefined reference to `i'
collect2: ld returned 1 exit status
I also tried
#include<stdio.h>
#include<temp2.h>
int main ()
{
extern i=6;
printf("The i is %d",i);
}
compiled this one
cc -I ./ temp3.c
got same error as in post 1
temp3.c: In function ‘main’:
temp3.c:5: error: ‘i’ has both ‘extern’ and initializer
So I have tried at least 3 different ways to use extern but non of them worked.
When you declare a variable using extern , you are telling the compiler that the variable was defined elsewhere and the definition will be provided at the time of linking. Inclusion is a different thing altogether.
extern
An external variable must be defined, exactly once, outside of any function; this sets aside storage for it. The variable must also be declared in each function that wants to access it; this states the type of the variable. The declaration may be an explicit extern statement or may be implicit from context.
-The C Programming Language
A variable must be defined once in one of the modules(in one of the Translation Units) of the program. If there is no definition or more than one, an error is produced, possibly in the linking stage (as in example 1 and 2).
Try something like the following
a.c
int i =10; //definition
b.c
extern int i; //declaration
int main()
{
printf("%d",i);
}
Compile, link and create an executable using
gcc a.c b.c -o executable_name
or
gcc -c a.c // creates a.o
gcc -c b.c // creates b.o
Now link the object files and create an executable
gcc a.o b.o -o executable_name
extern is declaration mechanism used to tell the compiler that the variable is defined in another file.
My Suggestion is that you define a variable in a ".c" file and then add the extern declaration in the corresponding ".h" file. In this way, the variable declaration will be available to all the source files which includes this header file and also it will be easier for one to identify in which ".c" it is actually defined.
The first program said:
The variable i (implicitly of type int) is defined somewhere else - but you didn't define it anywhere.
The second program tried to use a variable for which there was no declaration at all.
The third program tried to declare a variable without an explicit type (used to be OK; not allowed in C99), and said:
The variable i is defined somewhere else, but I want to initialize it here.
You are not allowed to do that.
So, the compiler is correct in all cases.
The declaration in the header 'temp2.h' should be fixed to extern int i; first. The implicit int is long obsolete.
You could fix the first example in several ways:
#include <stdio.h>
#include <temp2.h>
int main()
{
extern int i;
i=6;
printf("The i is %d",i);
return 0;
}
int i;
This defines the variable after the function - aconventional but legitimate. It could alternatively be in a separate source file that is separately compiled and then linked with the main program.
The second example could be fixed with:
#include <stdio.h>
#include <temp2.h>
int main()
{
int i=6;
printf("The i is %d",i);
return 0;
}
It is important to note that this example now has two variables called i; the one declared in temp2.h (but not actually referenced anywhere), and the one defined in main(). Another way of fixing it is the same as in the first possible fix:
#include <stdio.h>
#include <temp2.h>
int main()
{
i=6;
printf("The i is %d",i);
return 0;
}
int i;
Again, aconventional placement, but legitimate.
The third one can be fixed by similar methods to the first two, or this variant:
#include <stdio.h>
#include <temp2.h>
int i;
int main()
{
extern int i;
i=6;
printf("The i is %d",i);
return 0;
}
This still declares i in <temp2.h> but defines it in the source file containing main() (conventionally placed - at the top of the file). The extern int i; insides main() is doubly redundant - the definition in the source file and the declaration in the header mean that it does not need to be redeclared inside main(). Note that in general, the declaration in the header and the definition in the source file are not redundant; the declaration in the header provides a consistency check with the definition, and the other files that also use the variable and the header are then assured that the definition in the file containing main() is equivalent to the definition that the other file is using too.