C + extern declarations - Where to put them - c

Alright, I understand how the extern definition works but I don't know what would be the "best" place to put them. Consider the following file structure:
main.c / main.h / global.h
drv_adc.c / drv_adc.h
drv_pwm.c / drv_pwm.h
You might guess, this is quite common for a small microcontroller. The two drivers work on different parts of the hardware and have no interdependencies. Both drivers are able to set a flag (say: adc_irq_occured, pwm_irq_occured) which indicates something has happened and which will be handled in the main.c.
Now I can think of two approaches where I would put the "extern bool adc_irq_occured;" flag.
The drv_adc.h: It somewhat belongs to the ADC driver, therefore I could add it to its header file and instantiate it in the main.c.
I turn the logic around and place the extern declaration into my main.h (or global.h if it has to be so) and instantiate it in my drv_adc.c.
Now the question: Which option is the preferred option here? Is there any good book where I could read about such topics?

In main.c:
int flag = 0;
In main.h:
extern int myGlobal;
In drv_adc.c:
#include "main.h"
In drv_pwm.c:
#include "main.h"
Now that the variable is global , it is less secure , so use it with caution , and make sure any other drv files won't tamper with it.
-- EDIT --
Why not the other way round ?
We put the extern declaration in the header which is to be included by your other files. This is because we declare it once , telling the compiler that only one common version of the flag variable is available to both the drv files , which we included in the header , for more clarity do read this discussion , Difference between putting variables in header vs putting variables in source .

Related

c includes, preventing redundant code

If I have a c project where my main program needs file1 and file2 but file2 also needs file1. Is there a way I can get around including file2 in both main and file1? If I have an include guard, will this prevent file1.c from being added twice?
//file1.h
#ifndef FILE1_H
#define FILE1_H
void func1(void);
#endif
--
//file1.c
#include "file1.h"
void func1(void) {
..do something
}
--
//file2.h
#ifndef FILE2_H
#define FILE2_H
void func2(void);
#endif
--
//file2.c
#include "file2.h"
#include "file1.h"
void func2(void) {
..do something
func1();
}
--
//main.c
#include "file1.h"
#include "file2.h"
int main(void) {
func1();
func2();
return 0;
}
-- Since file2 includes file1, can I do this? will it prevent repetition of file1 code?
//main.c (alternate)
#include "file2.h"
int main(void) {
func1();
func2();
return 0;
}
I'm not too concerned about problems arising if file2 decides to no longer include file1 in the future. I'm much more concerned with wasted space.
What I'd like to know is A: does the include guard prevent the code duplication and if so, there is no additional space used by including file1 in both main.c and file2.c. B: in the case that extra space is being used, will my alternate main.c work?
Quick explanation (with the note that all of this can be overwritten by people that know what they are doing):
First of all, two definitions: declaration is when you write down that something exists. For example, "int foo();" or "struct bar;". Note that we can't actually use this thing yet, we've just given it a name. As long as you declare them as the same thing, you can declare things as many times as you want! (variable declaration has its own rules).
Anything you want to use needs to be declared before you reference it.
definition is when you say what the declaration is. int foo() {asdfadf;} or struct bar{int x;}. Things can be (and often are) defined when they are declared, but not always.
In C, you must follow the One Definition Rule. Things can be declared as often as you like, but they can be only defined once per translation unit (defined in one sec). (in addition, function calls can only be declared once per entire executable).
There are very few things that need to be defined before you use them...other than variables, you only need to define a struct before you use it in a context where you need its size or access to its members.
What is a translation unit? It is all the files used to compile a single source file. Your header files aren't targeted for compilation. Only your .c files (called "source files") are. For each c file, we have the idea of a "translation unit", which is all the files that are used to compile that c file. The ultimate output of that code is a .o file. A .o files contains all the symbols required to run the code defined in that c++ file. So your c file and any files included are withing the header file. Note: not everything declared in the translation unit needs to be defined in it to get a valid .o file.
So what is in a header file? Well (in general) you have a few things:
function declarations
global definitions & declarations
struct definitions & declarations
Basically, you have the bare bones declarations and definitions that need to be shared between the translation units. #include allows you to keep this in one shared file, rather than copying and pasting this code all over.
Your definitions can only happen once, so a include guard prevents that from being a problem. But if you only have declarations, you don't technically need and include guard. (You should still use them anyway, they can limit the cross-includes you do, as well as work as a guarantee against infinitely recursive inclusion). However, you do need to include all declarations relative to each translation unit, so you will most likely include it multiple times. THIS IS OK. At-least the declaration is in one file.
When you compile a .o file, the compiler checks that you followed the one definition rule, as well as all your syntax is correct. This is why you'll get these types of errors in "creating .o" steps of compilation.
So in your example, after we compile, we get file1.o (containing the definition of func1), file2.o (containing the definition of func2), and main.o (containing the definition of main). The next step is to link all these files together, using the linker. When we do, the compiler takes all these .o files, and makes sure that there is only one definition for each function symbol in the file. This is where the magic of letting main.o know what is in file1.o and file2.o happens: it resolves the "unresolved symbols" and detects when there are conflicting symbols.
Final Thought:
Keeping code short is kindof a misguided task. You want your code to be maintainable and readable, and making the code as short as possible is about the opposite of that. I can write a whole program on one line with only single letter alpha-numberic variables names, but no one would ever know what it did...what you want to avoid is code duplication in things like declarations. Maintaining a long list of #includes can become tricky, so it is often good to group related functions together (A good rule of thumb is that if I almost always use A and B together) then they should probably be in the same header file.
Another thing I occasionally (occasionally because it has some serious drawbacks) is to use a convenience header file:
//convience.h
#ifndef CONVIENIENCE_H
#define CONVIENIENCE_H
#include "file1.h"
#include "file2.h"
#endif
The convenience header file only has other header files in it, which ensures that it NEVER contains code, which makes it a little easier to maintain, but still kindof a mess. Also note that if you do the include guards in file1 and file2, the convienience guard isn't nessisary, though it can (theoretically) speed up compilation.
Why can't you have a single header where you can put both your functions func1() and func2().
Just include the header in different files.
Didn't get what you mean by code duplication.
//file1.h
extern void func1();
extern void func2();
//file1.c
#include<file1.h>
void func1()
{`
enter code here`
}
//file2.c
#include<file1.h>
void func2()
{
}
//main.c
#include <file1.h>
main()
{
func1();
func2();
}

What is the conventional way of defining macros in main.c that are needed in other header files?

For example I have a can.h header file that contains
#ifdef MC
extern int speed;
// many more variables and function prototypes
#endif
EDIT: I would want an option for the user to define MC that enables such variable and function prototypes. It is to be defined in C main alongside include directives (e.g. #define MC) however, other header files cannot link to main.c. Instead, i ended up defining such macros in can.h header itself. All i can think is writing a main.h too where can.h will include main.h. are there other ways to go around this problem?
It's not entirely clear to me what you are trying to do, but perhaps you want this:
/* in file can.h */
extern int speed;
and then
/* in file main.c */
#include "can.h"
int speed;
The header can.h just declares the existence of speed so that other modules can refer to it as an external symbol. The storage for this object is then allocated in main.c, when you write the the definition of speed.
You can either create a configuration header that has all the macros that you want defined and #include it in every header, or you can define configuration macros on the command line.
Use #include - Then you get those bits that you require
Inclusion is simply file content insertion by the preprocessor, anything declared or defined prior to inclusion will be defined in the include file. So:
#define MC
#include "can.h"
While that achieves what you have asked, I would not necessarily recommend it however, and might question the design.
You can have such macro added at your project level.
Such macro are also known as Preprocessor definitions. Visual studio provides such definition in project settings/configurations..
So you can have it added there and compile the solution for including mentioned declarations or remove it if you don't want to include it.
Adding the screen shot.

Multiple definition of token

Given the following code,
button.h
#ifndef BUTTON_H_
#define BUTTON_H_
#define true 1
#define false 0
#include <avr/io.h>
#include <avr/interrupt.h>
#include <timer0.h>
typedef struct {
unsigned char port;
unsigned char pin;
unsigned long timestamp;
} BUTTONS;
BUTTONS button_1;
BUTTONS button_2;
BUTTONS button_3;
enum BUTTONS_ID{BUTTONS_ID_1,BUTTONS_ID_2,BUTTONS_ID_3,BUTTONS_ID_COUNT};
BUTTONS* button[BUTTONS_ID_COUNT] = {&button_1,&button_2,&button_3};
void Button_init(void);
#endif //BUTTON_H_
and button.c
#include <button.h>
enum BUTTONS_state{BUTTON_STATE_UNPRESSED,BUTTON_STATE_DEBOUNCING,BUTTON_STATE_PRESSED};
int state = BUTTON_STATE_UNPRESSED;
void Button_init(void){
button[BUTTONS_ID_1]->port = PINB;
button[BUTTONS_ID_1]->pin = PINB4;
button[BUTTONS_ID_1]->timestamp = 0;
}
I get the following error : button.cpp : multiple definition of `button_1'. I know I must be doing something wrong. I am quite new at using structure the mistake must be coming from there. Basically I wanted to create button variable which I could access from my main program if need be. Is there a way to define them in my .h and initialize them within my .c and then access them from my main file?
Thank you
You've defined button1 and several other objects in your header file. If you include this header in multiple translation units (read: source files), you'll end up with one definition for each translation unit you compile. Then later, when you try to link -> KABOOM.
The simple solution is "don't put code that defines objects in your header." If you need to access them in multiple source files, you can leave the declarations, but you'll need to mark them extern. Then you can make the definition in a source file elsewhere.
You should not declare variables in header files. This is because when a header file is #included in a c file it is literally copied to it by the preprocessor.
So if 2 c files include the same h file, which in turn declares a variable, you end up with the same variable declared twice in both files. That's probably what happened here - you probably #included button.h in another c file.
The best way to make a variable application global is to declare it in only one file, and then declare it using extern in each c file where you want to use it.
In your example, do
BUTTONS button_1;
BUTTONS button_2;
BUTTONS button_3;
in one c file, and in all other c files where you want to use these vars, do:
extern BUTTONS button_1;
extern BUTTONS button_2;
extern BUTTONS button_3;
There is also other ways to do it. It's possible to use some preprocessor acrobatics and declare you variables in a header file in such a way that only in one file there are declared as global variables, and in all other files they are declared with extern. But personally I don't like this, because I do think that variables declaration do not belong in header files.
Besides, it's best to try not to use application global variables, which leads to ways of doing modular programming, low coupling and all that stuff. It's a very interesting and important topic, but is to wide for this answer.. :-)

C - Including variable (struct) declarations and functions in separate files

I am working on a C project in which part of the code is generated by a different application. The separate files would contain the following:
Type definitions, main(), and other functions
Variable declarations (whose type definition is in the file above) and functions to work with those variables
As mentioned, the information in the second file is generated by a different program, but it uses the type declarations in the main file. Similarly, the main program uses the variables and functions defined in the second file.
I have tried using the "include" and "extern" statements but have not been very successful at it. Since the two files are getting information from each other, would it be more useful to break them up in three files as follows?
1) Type definitions
2) Variable declarations (using the types defined in file 1) and related functions
3) Main() and the rest of functions that use the two above files
If this was the way to go, how would it work? Would it use include or extern, and how would I need to use these clauses?
Any help you can provide is greatly appreciated. Thank you!
There is nothing wrong with the layout you are suggesting. Perhaps some clarification on what extern and #include do would be helpful.
1) #include is a preprocessor directive which essentially says: `take the named file and pretend it is pasted in place of this directive'
2) extern is a C reserved word. Not to get into too many technicalities, but its meaning is: `the variable named in this statement is defined in a different place'. The space for a variable is reserved by the compiler exactly once, so if a function needs access to the variable in question, some information is needed before the definition is seen by the compiler. An extern declaration has enough information for the function to use the variable and the linker makes sure that a correct variable is used at a later stage.
So in your scenario, the file with type definitions will be #include'd in every file that refers to those types. If you want to collect all the variable definitions in one file, which will be compiled separately from other parts of your project, any file that uses those variables and will be compiled separately, needs to be supplied an extern declaration for each variable defined elsewhere. Note that if you simply include th file with variable definitions, the compiler will see the definition twice (first in the file with the definitions, then in the file that includes it) and assume you are trying to define each variable twice and will issue an error.
Finally, here is a simple scenario (it does not really make sense and is in bad style):
a.c---------
#include "t.h"
mytype a;
mytype b;
int f( int x, int y ) {
return (x + y)*a - b;
}
m.c---------
#include <stdio.h> // for stdout
#include "t.h"
#include "v.h"
int main () {
fprintf( stdout, "%d", a + b - f(1, 2) );
return 0;
}
t.h-----------
typedef int mytype;
v.h-----------
#include "t.h"
extern mytype a, b;
int f( int, int );
v.h and t.h can be combined (it is a question of style and the project requirements). Note that a declaration of f in v.h has an implied extern in front of it.
As outlined in a comment, you will almost certainly need a header — call it header.h — which will be included in both the file containing the main program (file 1, call it main.c) and in the generated file (file 2, call it generated.c).
The header file will contain the type definitions and shared function declarations (and, perish the thought, declarations for any global variables). It will be self-contained and idempotent (see, amongst others, the Stack Overflow questions What are extern variables in C?, Should I use #include in headers?, How to link multiple implementation files in C?, and Linking against a static library).
Both main.c and generated.c will include header.h. To ensure that header.h is self-contained, one (or both) of the files will #include "header.h" as the first header.
Finally fixed. If anybody else has the same problem, I followed Alexsh's steps but I also had to include guards in my .h files to prevent redefinitions (otherwise it wouldn't compile). Thank you very much to both Alexsh and Jonathan for their help!

What's the difference between using extern and #including header files?

I am beginning to question the usefulness of "extern" keyword which is used to access variables/functions in other modules(in other files). Aren't we doing the same thing when we are using #include preprocessor to import a header file with variables/functions prototypes or function/variables definitions?
extern is needed because it declares that the symbol exists and is of a certain type, and does not allocate storage for it.
If you do:
int foo;
In a header file that is shared between several source files, you will get a linker error because each source would have its own copy of foo created and the linker will be unable to resolve the symbol.
Instead, if you have:
extern int foo;
In the header, it would declare a symbol that is defined elsewhere in each source file.
One (and only one) source file would contain
int foo;
which creates a single instance of foo for the linker to resolve.
No. The #include is a preprocessor command that says "put all of the text from this other file right here". So, all of the functions and variables in the included file are defined in the current file.
The #include preprocessor directive simply copy/pastes the text of the included file into the current position in the current file.
extern marks that a variable or function exists externally to this source file. This is done by the originator ("I am making this data available externally"), and by the recipient ("I am marking that there is external data I need"). A recipient with an unsatisfied extern will cause an Undefined Symbol error.
Which to use? I prefer using #include with the include guard pattern:
#ifndef HEADER_NAME_H
#define HEADER_NAME_H
<write your header code here>
#endif
This pattern allows you to cleanly separate anything you want an outsider to have access to into the header, without worrying about a double-include error. Any time I have to open a .c file to find what externs are available, the lack of a clear interface makes my soul gem crack.
There are indeed two ways of using functions/variables across translation units (a translation unit is usually a *.c/*.cc file).
One is the forward declaration:
Declare functions/variables using extern in the calling file. extern is actually optional for functions (functions are automatically extern), but not for variables.
Implement the function/variables in the implementing file.
The other is using header files:
Declare functions/variables using extern in a header file (*.h/*.hh). Still, extern is optional for functions, but not for variables. So you don't normally see extern before functions in header files.
In the calling *.c/*.cc file, #include the header, and call the function/variable as needed.
In the implementing *.c/*.cc file, #include the header, and implement the function/variable.
Google C++ style guide has some good discussions on the pros and cons of the two approaches.
Personally, I would prefer the header file approach, as it is the single place (the header file) a function signature is defined, calling and implementation all adhere to this one piece of definition. Thus, there would be no unnecessary discrepancies that might occur in the forward declaration approach.

Resources