This question already has answers here:
Header per source file
(7 answers)
Closed 5 years ago.
when i'm reading some tutorial in C programming,all of them said that we need to put only structure type declarations, function prototypes, and global variable extern declarations, in the .h file; and for the function definitions and global variable definitions and initializations we need to put them in the .c file.
but when i try to put the content of the function in the header file it works fine. if it works fine why we must not use it ?
in the sum.h :
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED
#include<stdio.h>
#include<stdlib.h>
int sum(int a,int b)
{
return a+b;
}
#endif // HEADER_H_INCLUDED
int the main.c:
#include "sum.h"
int main()
{
printf("%d\n",sum(1,2));
return 0;
}
Broadly, you might what to include your header in multiple source files. If you have actual function definitions in there, you're going to have multiple definitions. This will be fine until the linker tries to assemble your compiled sources into an executable or library, at which point it will fail because it finds several functions with the same name.
Related
I am trying to enable a set of functions from a header only if a macro is defined
I define the macro before including anything and it reaches the .h file and highlights the proper functions, but it does not reach the .c file so I can call the functions with the right prototypes but they have no definition since the .c file does not see I defined the macro
Is there some way to get this to work without having to stuff all of the .c code inside the .h file?
example:
test.h:
#ifdef _ENABLE_
int enabled_function(int a, int b);
#endif
test.c:
#ifdef _ENABLE_
int enabled_function(int a, int b)
{
return a + b;
}
#endif
main.c:
#define _ENABLE_
#include "test.h"
int main()
{
printf("%d", enabled_function(10, 10));
}
you need to use conditional compilation in both header and C file
in header file:
#define SOMETHING
#ifdef SOMETHING
int a(int);
int b(int);
int c(int);
#endif
In the C file:
#include "header_file_with_SOMETHING_declaration.h"
#ifdef SOMETHING
int a(int x)
{
/* ... */
}
int b(int x)
{
/* ... */
}
int b(int x)
{
/* ... */
}
#endif
Your source files test.c and main.c represent separate translation units. The macro definitions declared in one are not visible to the other.
Declarations that need to be visible across multiple translation units, whether of macros or of anything else, generally should go into header files that all translation units wanting them #include. It is possible to have a header that serves the sole purpose of defining macros that control configuration options, that you would create or update prior to compilation. There are tools that automate that sort of thing, but they are probably much heavier than you require for your purposes right now.
For macros specifically, most compilers also offer the option of specifying macro definitions via compiler command-line arguments.
Either way, no, your definition in main.c of macro _ENABLE_ will not be visible in test.c. (And no, you shouldn't merge test.c into test.h.)
But you should also consider whether you actually need any of that. Certainly there are use cases for cross-translation-unit build-time configuration, but what you present does not look like one of them. It is rarely very useful to suppress the compilation of a function just because you know you're not going to call it. it is usually better to either remove it altogether or to leave it, uncalled. In the latter case, your linker might even be smart enough to omit unused functions from the final binary.
"Is there some way to get this to work without having to stuff all of the .c code inside the .h file?"
and from comments...
"...but I wish to be able to define the macro in my main file and have it be visible from the .c file too
So, you are asking to #include one .c file into another .c file. This is doable with caution. But because a .c file containing the main() function cannot be #include into another .c file without invoking a multiply defined symbol error for main(...), it has to be the other way around. That is a dedicated .c file (eg. enabled.c) could be created that contains all of the #defines function prototypes and definitions. This .c file can then be #included into main.c to hopefully satisfy a variation of what you are looking for.
Following is tested source code that does this:
enable.c
#define _ENABLE_
//test criteria - then create prototype of enabled_function
#ifdef _ENABLE_
static int enabled_function(int a, int b);
#endif
#ifdef _ENABLE_
static int enabled_function(int a, int b)
{
return a + b;
}
#endif
static int use_enabled_function(int a, int b);
//This will be created with or without _ENABLE_, but its
//definition changes based on whether _ENABLE_ exists or not.
static int use_enabled_function(int a, int b)
{
#ifdef _ENABLE_
return enabled_function(a, b);
#elif
return -1;
#endif
}
main.c
#include "enable.c"
int main(void)
{
//test criteria - then use enabled_function
#ifdef _ENABLE_ //must include test for existence before using
printf("%d\n", enabled_function(10, 10));
#endif
//no need to test criteria here (tested internally)
printf("%d\n", use_enabled_function(10, 10));
return 0;
}
I wrote a minimal code to test the working of guard macros in C. I read that they prevent the header file to be read again by the compiler if it has done already. Here is my header file:
#ifndef TEST_H
#define TEST_H
#include<stdio.h>
int num=12;
#endif
Here is my main function:
#include"headers.h"
int main()
{
p2();
return 0;
}
Here is the p2 function called in main():
#include"headers.h"
void p2()
{
printf("p2 running\n");
}
While compilation it is giving me error of redefinition of num. Should macro TEST_H not prevent multiple definitions error of num here ?
Also if I replace int num=12; with int num; , without any other modification, It does not show any error. Should int num; must not be a definition of num(as it will be initialized to 0) and compiler should again show same error of multiple definitions of num?
Let me answer to each of your questions:
The macro TEST_H prevents any multiple inclusion of the content of headers.h file in a translation unit, i.e. in a C source file. In your case, it works: you have only one definition of num in each C file. The raised error probably comes from the linker, which finds two definitions of the same variable in the linked code.
If you replace int num=12; with int num;, then it become a tentative definition as commented by #RobertoCaboni: to summarize, you authorize the compiler/linker to consider this instruction either as a definition (the first time it is encountered) or a declaration (the next times it is encountered). So you do not have any more error with multiple definitions. The initialization to 0 will depend on your linker configuration and/or your source code.
Should macro TEST_H not prevent multiple definitions error of num here ?
No. Each c file or translation unit compiled separately and header guard avoids multiple definitions within transaction unit.
In preprocessing stage of compilation all header files declared in a transaction unit are copied,macro's are expanded and many more things are done. refer for more details.
Understand how header guard is working,
//test.h
#ifndef __TEST_H__
#define __TEST_H__
int num=12;
#endif
If Multiple includes of same headers,
//main.c
#include "test.h"
#include "test.h"
int main(){
}
Translates as below during per-processing stage of compilation and conditional compilation part of code will be removed.
#ifndef __TEST_H__
#define __TEST_H__
int num=12;
#endif
//as __TEST_H__ is already defined subsequent inclusion of test.h has no effect
#ifndef __TEST_H__
#define __TEST_H__
int num=12;
#endif
int main(){
}
And Hence compiler will not detect any conflict with multiple definition of num.
Linking takes one or more object files or libraries as input and combines them to produce a single (usually executable) file. In doing so, it resolves references to external symbols, assigns final addresses to procedures/functions and variables, and revises code and data to reflect new addresses (a process called relocation). Which detects multiple instance of the same variable and throws link time error for multiple definition.
Should int num; must not be a definition of num(as it will be initialized to 0) and compiler should again show same error of multiple definitions of num?
There has to be exactly one definition of any functions or initialized global variables, but the definition of an uninitialized global variable can be treated as a tentative definition. C then allows (or at least does not forbid) different source files to have tentative definitions for the same object. (source)
What are advantages and disadvantages of both approaches?
Source vs. header implementation
Function definition inside source file
Header file sourcefunction.h contains declaration only.
#ifndef SOURCEFUNCTION_H
#define SOURCEFUNCTION_H
void sourcefunction(void);
#endif // SOURCEFUNCTION_H
Source file sourcefunction.c contains definition
#include "sourcefunction.h"
#include <stdio.h>
void sourcefunction(void) { printf(" My body is in a source file\n"); }
Function definition inside header file
Header file headerfunction.h contains definition which is the declaration at the same time.
#ifndef HEADERFUNCTION_H
#define HEADERFUNCTION_H
#include <stdio.h>
void headerfunction(void) { printf(" My body is in a header file\n"); }
#endif // HEADERFUNCTION_H
No source file is needed.
Consumer
File main.c
#include "sourcefunction.h"
#include "headerfunction.h"
int main(void) {
sourcefunction();
headerfunction();
return 0;
}
Why compile many source files?
We have to compile all source files and remember about them during linking.
gcc -c sourcefunction.c
gcc -c main.c
gcc main.o sourcefunction.o
Make can handle file managing but why even bother?
Is separation of interface and implementation always an issue?
It is obvious reason for big projects and teamwork. The designer specifies the interface. The programmers implement functionality.
What about smaller projects and non-formal approach?
Is removing definition from header files always preventing from linker errors?
Let's assume my program is using another module that defines the function with the same name sourcefunction().
#include "sourcefunction.h"
#include "sourcefunction1.h"
#include "headerfunction.h"
int main(void) {
headerfunction();
sourcefunction();
return 0;
}
Different function interface
File sourcefunction1.h
#ifndef SOURCEFUNCTION1_H
#define SOURCEFUNCTION1_H
int sourcefunction(void);
#endif // SOURCEFUNCTION1_H
File sourcefunction1.c
#include "sourcefunction1.h"
#include <stdio.h>
int sourcefunction(void) { int a = 5; return a; }
By compiling main.c, I get a nice compiler error
sourcefunction1.h:4:5: error: conflicting types for 'sourcefunction'
showing me the location of error.
Same function interface
File sourcefunction1.h
#ifndef SOURCEFUNCTION1_H
#define SOURCEFUNCTION1_H
void sourcefunction(void);
#endif // SOURCEFUNCTION1_H
File sourcefunction1.c
#include "sourcefunction1.h"
#include <stdio.h>
void sourcefunction(void) { int a = 5; printf("%d",a); }
Compiler does not mind multiple declarations. I get ugly linker error.
Can header implementation serve as library?
jschultz410 says
If you are writing a library and all your function definitions are in headers, then other people who do segment their development into multiple translation units will get multiple definitions of your functions if they are needed in multiple translation units
Lets' have
File consumer1.c
#include "headerfunction.h"
void consume1(void) { headerfunction(); }
File consumer2.c
#include "headerfunction.h"
void consume2(void) { headerfunction(); headerfunction();}
File twoConsumers.c
extern void consume1(void);
extern void consume2(void);
int main(void) {
consume1();
consume2();
return 0;
}
Let's compile sources.
gcc -c consumer1.c
gcc -c consumer2.c
gcc -c twoConsumers.c
So far, so good. Now, linking.
gcc consumer1.o consumer2.o twoConsumers.o
Linker error: multiple definition of 'headerfunction', of course.
But I can make my library function static.
File headerfunction.h, afterwards.
#ifndef HEADERFUNCTION_H
#define HEADERFUNCTION_H
#include <stdio.h>
static void headerfunction(void) { printf(" My body is in a header file\n"); }
#endif // HEADERFUNCTION_H
It hides the definition from other translation units.
I shouldn't answer this, but I will.
This can create duplicate definitions unless you really only have a single .c file in your project (unwise). Even the header guards won't prevent files the headers from being included multiple times if those multiple times are with different .c files. When the .obj files are linked together, there will be conflicts.
If only the function declaration and not definition is in the header, then only changes to the interface (the function name, parameters or return type) require recompiling dependencies. However, if the entire definition is in the header, then any change to the function requires recompiling all .c and .h files that depend on it, which, in a larger project, can create a lot of unnecessary recompiling.
It's not the convention. Libraries will not use this convention, so you'll be stuck dealing with their header file structure. Other developers will not use this convention, so you can create confusion or annoyance there.
This question already has answers here:
Multiple definition of ... linker error
(3 answers)
Closed 8 years ago.
I am developing a program to read NFC cards, and I have a header file, source.h, holding all the variables for use in it's related source code, source.c. A sample is as shown below:
#ifdef __cplusplus
extern "C" {
#endif
int SDA_SUPPORT_PRESENT = 0;
int DDA_SUPPORT_PRESENT = 0;
int CDA_SUPPORT_PRESENT = 0;
int CARDHOLDER_VERIFICATION_PRESENT = 0;
...
The source code, source.c, holds the methods utilizing the above defined variables. A sample is as shown:
#include <source.h>
extern void translateError(uint8 error, int slot) //one of the methods
{
TP_DbgSerialPrn("\n\rDevice Error: ");
switch(error)
{
...
I also have a source file, CardReader.c, which calls the methods included in source.c, and which has a related header file, CardReader.h. The issue is, when I include the source.h file in the CardReader.h file, i get the following error:
../CardReader.o:(.bss+0x12b4): first defined here
../source.o:(.bss+0x12b8): multiple definition of `SLOT_NUMBER'
../CardReader.o:(.bss+0x12b8): first defined here
../source.o:(.data+0x49): multiple definition of `LISTED_APPLICATION_IDS'
../CardReader.o:(.data+0x49): first defined here
../source.o:(.data+0xc9): multiple definition of `LISTED_APPLICATION_IDS_LENGTH'
All the rest of the error messages are of the same type. The source.h file is included as indicated in CardReader.h:
#include <TPCardReader.h>
#include <source.h>
#ifdef __cplusplus
extern "C" {
#endif
...
with the path variables set properly, so it can be found, and then called the CardReader.h file as usual in CardReader.c. My question is why is that error coming up, yet I have only defined each of the specified variables once in source.h? Is there something am missing or not doing or do I not understand the error?
The variables should not be defined in the header file.
Instead in the header file you should have
extern int SDA_SUPPORT_PRESENT;
Then in the source (.c) file you should have
int SDA_SUPPORT_PRESENT = 0;
This will ensure you only have one definition of the variable
But then again global variables are a bad idea
I had to write few functions which are very long. So, I decided to put them in different files and link them to main.. so that it works as if I wrote function definitions after main().
How do I do it..
In a .h file you put your prototype
#ifndef MY_HEADER_H
#define MY_HEADER_H
void hello(void);
#endif
In a seperate .c file you implement your function such as hello.c
#include "myheader.h"
void hello()
{
printf("Testing function from other file\n");
}
then in main you do
#include "myheader.h"
int main()
{
hello();
return 0;
}
make sure you compile hello.c into hello.o before linking the files or it will tell you that it can't resolve the reference to hello.
Find create a header file that has a file ending of .h .
Lets say this header file is named blah.h.
The general structure of this header will be
#ifndef BLAH_H_INCLUDED
#define BLAH_H_INCLUDED
//code
#endif // BLAH_H_INCLUDED
Those are header guards, to prevent multiple inclusions.
Inside the code you will still your function declarations.
For example, void function(int blah); would be a valid function declaration.
This file is then included at the top of all of your files that uses or defines the functions declared, #include "blah.h"
Then you can define your functions in the other files, and when you link them together the program will work.