Suggest you re-read the thread. The whole point is that you (almost) never name a .c file in a #include
You add the .c that contains routines to be used to the list of files to be compiled/linked. Then you #include the .h that documents the interface to those routines in the other .c files that want to make use of the functions offered.
Posted by JohanEkdahl: Sat. Feb 26, 2011 - 06:53 PM
1
2
3
4
5
Total votes: 0
Quote:
"usart.h" does not need to include "usart.c" is that true?
Technically, that is correct. You can have the prototypes in uart.h, the implementations in uart.c w/o #include'ing uart.h, and then #include uart.h in main.c and call the funxtions. The compiler/linker will not complain.
But for me the header files should be seen as specifications of interfaces that both implementors and callers adhere to. Thus they should both include the interface specification.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
can you please explain bit more about Declaration and Definition, difference b/w them.
You have read the entire tutorial / thread haven't you?
But in short:
Declaration: usually found in a .h file - opportunity to make the compiler aware of a function/variable's existence and provide details about the types involved. In the case of a function you can tell it's a declaration because it ends with a semi-colon rather than braces containing statements. In the case of a variable you can tell it's a declaration as it starts with the word 'extern' (you can put the word 'extern' on a function declaration too if you like but don't need to as it's obvious from the fact there's no function body). Declarations (as long as they agree) may occur multiple times. Declarations do not lead to any storage being allocated, they are only to let the compiler (and reader) know about types involved.
Definition: Usually found in a .c file. This is the thing that actually allocates storage and creates something in memory - whether it be the storage to hold a variable or the opcodes that implement a function. A variable definition is obvious by the fact that it does not contain the word 'extern' and a function definition is obvious by the fact that the function header ("prototype") is followed by a statement block contained in braces ({}) which hold the C statements that implement the operation of the function. Definitions must only appear once within all the files passed to the linker and are therefore usually contained in a single .c file.
Example:
//foo.h - declaration of a variable and function
extern int n;
long my_function(int number, char c);
//foo.c - definition of a variable and function
int n;
long my_function(int number, char c) {
return c * number;
}
Ya i had gone trough the tutorial. It is too good and informative.
Quote:
In the case of a function you can tell it's a declaration because it ends with a semi-colon rather than braces containing statements. In the case of a variable you can tell it's a declaration as it starts with the word 'extern' (you can put the word 'extern' on a function declaration too if you like but don't need to as it's obvious from the fact there's no function body)
what about in the the below code if foo.h is not used?
//foo.c - definition of a variable and function
int n; //will be definition as well as declaration,right?
long my_function(int number, char c) {
return c * number;
}
Posted by JohanEkdahl: Mon. Mar 21, 2011 - 09:41 AM
1
2
3
4
5
Total votes: 0
Both n and my_function are definitions as well as declarations.
Think of definition as "implementation". Where a variable is actually allocated, or the body of a function is given.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
Personally I wouldn't confuse myself by calling them both definitions and declarations. Both lead to memory being allocated so, in my book, they are definitions. But clearly, once the compiler has encountered a definition it knows the types involved so I guess in that sense you might also use the term declaration but this seems to be trying to over-complicate something that is really very simple:
Posted by JohanEkdahl: Mon. Mar 21, 2011 - 01:15 PM
1
2
3
4
5
Total votes: 0
I see your point, Cliff.
For me it is rather like:
A definition is implementing something (and it might lead to memory allocation).
A declaration is about "making the existence of something known" (leading to an entry in the compiler symbol table if the thing is not already there, could lead to an update even if it was already there, and could lead to an entry in the table of unresolved references left to the linker).
A Definition is inherently a declaration.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
Agreed but I think it actually helps the learner to think of them as two distinct things. Declaration=type-info/header(usually), Definition=allocation/C file. Anything more over-complicates and begins to lose the point about where they should be located and why which is the key thing.
I have a different method of using headers which works out well for me so I thought it might be worth a mention.
Any #define's which are only accessed within the modules .c file, are simply placed at the top of the .c file. Only parts of the module which must be accessed externally go into the .h file. Then all .h files get included into one file called includes.h which is included at the start of every .c file.
I have done some large projects like this, and have never needed to use #ifndef.
Telling yourself something is too hard, or too complicated, is not a determination. It is a decision.
Posted by JohanEkdahl: Fri. Jul 22, 2011 - 07:28 AM
1
2
3
4
5
Total votes: 0
Quote:
Only parts of the module which must be accessed externally go into the .h file.
This boils down to your header files being the interface to the module and nothing else, which in my view is a beautiful thing.
Wether the defines etc that are needed only inside the volume is placed in the source 'per se' or in another header file is another matter, where my opinions are less strong. But note that a header file will likely be needed for that too, if the 'module' becomes large enough to warrant splitting it's implementation into several .c source files.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
I wish to be able to use fprintf() or fprintf_P() from many different c files in project to send data out via a USART. The problem that arises is the first argument (i.e., FILE *stream) in AVRs w/ multiple USARTS. As a cheat, I would do something like:
#define comExt (&com0_str)
extern FILE com0_str;
in some "global" projDef.h file. com0_str would be declared elsewhere in a "*Msg.c" as
This c file then would be the only one that reaches out and touches the "com ports". However, this still leads to the problem that every module that includes this submodule would need to know what the two com ports (in a given AVR w/ two ports) are. What is the best solution to this problem?
How is that a "cheat". Defining it in one C file and declaring it extern for the others that need to use IS the right way to do this?!? Not sure the point of your macro though?
It is a cheat because my modules are not independent. Meaning, if I have a display.h and display.c file pair whose purpose is to provide an interface to a commercial display, I would like that module to be portable to many projects. However, as soon as I include the fprintf statements, it needs some overarching project definition header file to glue the project together. If I use comExt in one project and comInt in another, I would need to change the code in the display module.
The macro is just to make things neater, to abstract the pass by reference nature of the FILE argument. If I remove the macro, I could put multiple extern definitions of the port in all of my module header files, still only declaring it once (I think). However, I think the naming issue for portability remains.
I still don't get your problem? What's wrong with simply doing the equivalent of:
Quote:
As a cheat, I would do something like:
How is that a "cheat". Defining it in one C file and declaring it extern for the others that need to use IS the right way to do this?!? Not sure the point of your macro though?
The only problem is that second.c relies on the variable being declared as uart_str in some other file. If second.c gets reused in another project that defined it as uart0_str or uart1_str, second.c would need to be changed. Maybe this is unavoidable.
I cannot see a way to avoid it - the object has to be instantiated somewhere. Perhaps the "client" should be told to own it? They actually define it in their main.c (or whatever).
Having said that surely the FILE used for uart_str would be located with UART_init, UART_putchar() and others in uart.c and a lcd_str would be created with LCD_init(), LCD_putchar() and so on in lcd.c ?
Thanks for the advice. My setup is currently as in your example.
I think there was a miscommunication regarding the "str" for the LCD. The display module (used as an example here, really I meant any module) does not itself communicate via a UART. It uses some other interface (i.e., I2C or SPI). I want the display module to be able to print informational messages out the "external" uart to be monitored by some third party -- there is only one uart_str.
If you want the output of a module to be more universal, then the module could contain a FILE* which either gets loaded directly by main, or via a function.
The tutorial is very good - I used similar modules in a project containing about 40 source files.
A small hint to improve the source readability:
Use a template for your .c and .h files.
The example below is for a smaller project, a controller for a brushless DC motor. It includes comments for Doxygen. The template.h is similar
/*! \file NAME.c
\brief description
*/
/* Include files */
#include "config.h"
#ifdef SYMBOL
#include
#include "file"
/********************
local RAM variables with initialisation as needed
*********************/
/********************
local PROM variables with initialisation
*********************/
/********************
local EEPROM variables with initialisation
*********************/
/********************
external variable and function definitions in order
RAM, PROM, EEPROM, functions
*********************/
/* **************** AVRDSS ****************/
/* ************** BLDControl **************/
/* ************** commutator **************/
/* *************** dispatch ***************/
/* ***************** PID ******************/
/* ***************** PLL ******************/
/********************
Functions
*********************/
/********************
Interrupt service routines
*********************/
/********************
Event handlers
*********************/
#endif /* SYMBOL */
Try to keep header files as local as possible to what they document. Not everyone who includes your uart.h necessarily wants an inclusion of avr/io.h and especially avr/pgmspace.h forced upon them.
What you can do is use those files own header protection to give warnings about their requirement. Say your uart.h uses types such as uint8_t which are indirectly defined by the inclusion of avr/io.h you could rely on the fact that the io.h has this:
#ifndef _AVR_IO_H_
#define _AVR_IO_H_
So in your own header file you could include:
#ifndef _AVR_IO_H_
#error "uart.h requires avr/io.h to be included before it"
#endif
I generally don't use header files, I just declare everything (relating to that module) at the top of each code module. Seems quicker from an editing point of view and reduces the number of files involved.
But I frequently have to put #include et al at the top of each code module. Is there a danger in having the same header file appear multiple times like this at the top of multiple modules.
I use:
AS6 (under duress)
WinAvr 20100110
Windows 10
STK 600
AVR ONE!(broken and Atmel won't fix)
JTAGICE3 (only works with AS6)
AVRISP II
So far - '88 '2560
Sometimes my own RTOS
I generally don't use header files, I just declare everything (relating to that module) at the top of each code module. Seems quicker from an editing point of view and reduces the number of files involved.
But I frequently have to put #include et al at the top of each code module. Is there a danger in having the same header file appear multiple times like this at the top of multiple modules.
Those comments seem to suggest you really haven't got the concept of header files. The #include basically just pastes the included file into the file that has the #include - no magic. Consider the instance where you #include that file into another file that has already #included the file - you have two instances of that file - thus the compiler will complain. Understand the concept, follow the rules and life will be good.
I used to use them all the time for larger projects, but I find that with smaller MCU code, I would rather have the function declarations and variable definitions at the top of the .c module than having a separate file open. Just laziness more than anything else.
My question is if I have a program comprised of three .c modules and each of them have a io.h (or any other include) file included at the top, is there any danger? The compiler does not complain. Actually it will not compile if I don't do it. I could make a foo.h to go with my foo.c and put the io.h file inside the foo.h but that seems pointless.
I use:
AS6 (under duress)
WinAvr 20100110
Windows 10
STK 600
AVR ONE!(broken and Atmel won't fix)
JTAGICE3 (only works with AS6)
AVRISP II
So far - '88 '2560
Sometimes my own RTOS
Consider the instance where you #include that file into another file that has already #included the file - you have two instances of that file - thus the compiler will complain.
No it won't. is set up correctly so that the already knows that it has been included.
Quote:
I would rather have the function declarations and variable definitions at the top of the .c module
That works for that file, but what if you need those variables and functions visible is multiple other files? Then you need to declare those functions and variables multiple times. Put them into a .h file, then you need only declare them once.
Quote:
My question is if I have a program comprised of three .c modules and each of them have a io.h (or any other include) file included at the top, is there any danger?
No, not at all. Separate .c files are just that, separate. None know what files the others include.
Posted by JohanEkdahl: Thu. Aug 16, 2012 - 07:25 AM
1
2
3
4
5
Total votes: 0
Quote:
Those comments seem to suggest you really haven't got the concept of header files.
And even more so the concepts of function prototypes, typedefs and extern declarations.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
Now in main.c you want to call those functions. How on earth can you achieve that? How can the compiler know when it encounters a call to:
foo = ADC_Read();
or
ADC_change_channel(5);
what the input or return parameter types are? This is the whole reason you would have adc.h:
// adc.h
int ADC_init(void);
uint16_t ADC_read(void);
void ADC_change_channel(uint8_t chan);
It would be #include'd in main.c so the compiler knows what the interface to each of the routines is. This is pretty fundamental to the use of the C programming language, ignore it at your peril.
Posted by JohanEkdahl: Thu. Aug 16, 2012 - 10:28 AM
1
2
3
4
5
Total votes: 0
I believe that it is important for the understanding of this to keep the concepts of prototypes, typedefs and externals apart from the concept of the #include mechanism as such. Together they form a powerful mechanism for structuring projects on the source file level, but taking them apart will reveal what is actually going on and helps understanding what this is all about.
As short as I can manage:
Using Cliffs example, suppose you have functions for handling the ADC in a separate source file adc.c, but you want to call these functions from another source file, say main.c . Now purely technically you might get away without having any prototypes in adc.h but just the definitions (implementations) of the functions. In main.c you definitively must have prototypes for the functions, or else (as Cliff points out) the compiler will not know about parameter and return types etc.
But (and that is a big BUT): If you at some time change the actual definitions (implementations) of the functions in adc.c, but fail to update the prototypes in main.c the result will likely be disastrous. Since the compiler actually compiles each C source file separately it will not spot the mismatch. The linker will then happily resolve the calls from main.c to functions in adc.c – but since the code from main.c will push different parameters from what the code from adc.c expects everything will be a mess. You will not get any build errors, but you application will likelt crash at run time.
The solution is to make sure that the very same prototypes are seen in both adc.c and main.c. I am not speaking about two prototypes that look identical (because, again, with time one of them will change but not the other). I am talking about the two source files actually “seeing†the same prototype. The solution is to place such prototypes in a text file that is then inserted into both source files just before compilation proper takes place. This is what header files and the #include pre-processor directive is all about.
Now when you change an implementation in adc.c but fail to change the corresponding prototype in adc.h, the compiler will emit an error when compiling adc.c. You now change the prototype, but fail to change the actual call (e.g. adding a newly introduced parameter) in main.c – and the compiler will emit an error compiling main.c. When that also is corrected the application builds clean.
Think of an include file as a contract between the supplier (implementation) and consumer (caller) of some functionality. Both ends must “do the same thing†or you will get a build error. Without that contract you will get a runtime error. A build error is always preferable to a runtime error.
I cannot see how you can get around this if you have several source files. If you actually have your prototypes only in main.c and implementations in adc.c, then you need to rethink and take in what I describe above. Effectively, you are satisfying the compilers need for knowing how to call the functions, but lose out on the advantages you can get from a common include file. Ignoring this will lead to disaster sooner or later. Probably sooner..
Not so short after all, but I hope it helps to clear up what this is really about.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
Guys, my original question was:
"Is there a danger in having the same header file appear multiple times like this at the top of multiple modules." Like io.h.
I do use a .h file if I find I want to put all the prototypes and variable declarations in one place. Sometimes. Most of the time they are at the top of my main source code module. If I want to re-use a bunch of stuff then I create a .h file for the module so I don't have to do much work the next time around.
I do use typedefs when I want to get a bit more portable.
I understand and use extern when needed.
I just asked what was going to happen if I put #include io.h at the top of each c module to make the compiler happy.
I do appreciate the extention of the tutorial but to extrapolate from my original question and statement that I prefer to put everything at the top rather than a separate .h file means I lack a bunch of understanding was a touch pedantic and condecending, don't you think?
I use:
AS6 (under duress)
WinAvr 20100110
Windows 10
STK 600
AVR ONE!(broken and Atmel won't fix)
JTAGICE3 (only works with AS6)
AVRISP II
So far - '88 '2560
Sometimes my own RTOS
I may have a module called read_gps.c
I call it and it returns a variable.
My main module would have the prototype for read_gps(xxx) But the read_gps.c module may have 50 functions to do its work. And all 50 functions may have their prototypes at the top of that code module.
Why is that a sin?
I don't and won't ever need to call any of those internal functions from anywhere else. I can make a single read_gps.h file and include the prototype for the read_gps(xxx) but that is just as much work or more than putting the prototype along with the others at the top of the main module.
I can put all the prototypes for the internal read_gps.c file in read_gps.h but then I would have to include it in two places to get the compiler to work.
I can have two .h files, one containing the read_gps(xxx) prototype to include in the main module and another containing all the internal module protypes to include inside the read_gps.c module but that is just for housekeeping. In this case I see no added value of header files.
I use:
AS6 (under duress)
WinAvr 20100110
Windows 10
STK 600
AVR ONE!(broken and Atmel won't fix)
JTAGICE3 (only works with AS6)
AVRISP II
So far - '88 '2560
Sometimes my own RTOS
Posted by JohanEkdahl: Thu. Aug 16, 2012 - 04:01 PM
1
2
3
4
5
Total votes: 0
Extrapolationg, you said? For functions that are both defined in and called from one and the same source file you do not need to have prototypes in a separate header file. I never said that.
I wasn't my meaning to be condecending. Every time one answers, one has to make some assumption of the knowledge and skill level of the intended receivers/readers. If I missed the mark widely this time, I did that. Period.
OTOH, when you're saying
Quote:
I can make a single read_gps.h file and include the prototype for the read_gps(xxx) but that is just as much work or more than putting the prototype along with the others at the top of the main module.
it seems to me that you've missed the point. The prototype for read_gps() should be seen in two source files, not only in the main module. If you actually type it into both files then i) this will be un-necessary work, and ii) it will not in any way "guarantee the contract".
Quote:
I just asked what was going to happen if I put #include io.h at the top of each c module to make the compiler happy.
Nothing bad, since that header file is nicely written and following good conventions. The compiler will use the parts of it that it needs, and the rest of the stuf in it will not be used.
Quote:
I do use a .h file if I find I want to put all the prototypes and variable declarations in one place.
I am a bit uncertain what is meant by "variable declarations" above, but if it is something like
int foo;
then this will spell problems when the header file in inluded into more than one source file. The root of the problem isn't the inclusion into two source files, but having the variable definition in the header file. They should go into .c source files just like function implementations.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
If you look at any "standard" header file such as those within the AVR-LibC collection you will see they all have protection like this. If main.c then said (in error):
then on the first inclusion of adc.h the _ADC_H_ define is not made so the bit between #ifndef and #endif is used. This introduces all the types/interfaces and, inportantly now #define's _ADC_H_.
Now when it gets to the second (perhaps indirect) #include "adc.h" the _ADC_H_ symbol is already defined so the entire section between #ifndef and #endif is ignored this and all subsequent times.
THAT is the way you ensure that it doesn't matter if there are multiple inclusions of a .h file.
EDIT: BTW just looked at the universally used and guess what...:
#ifndef _AVR_IO_H_
#define _AVR_IO_H_
PS the annoying thing is that I even realised I'd forgotten to mention the header protection thing when I was sat in the local health centre having an ECG for a suspected heart attack (luckily not it turns out) but I was only just allowed back near a PC just now by she who must be obeyed.
I wasn't my meaning to be condecending. Every time one answers, one has to make some assumption of the knowledge and skill level of the intended receivers/readers. If I missed the mark widely this time, I did that. Period..
Sorry, was not directed at you. The initial reply to my initial question didn't answer my question but did question my understanding.
Quote:
I am a bit uncertain what is meant by "variable declarations" above, but if it is something like
.
int foo;
Quote:
then this will spell problems when the header file in inluded into more than one source file. The root of the problem isn't the inclusion into two source files, but having the variable definition in the header file. They should go into .c source files just like function implementations.
I should have specified, global variables. I have placed global variables in a .h at times. Most of the time my .h files just have function prototypes, defines and typedefs. But now-a-days, I don't use many .h files. I just put it all in the code.
I use:
AS6 (under duress)
WinAvr 20100110
Windows 10
STK 600
AVR ONE!(broken and Atmel won't fix)
JTAGICE3 (only works with AS6)
AVRISP II
So far - '88 '2560
Sometimes my own RTOS
Posted by JohanEkdahl: Thu. Aug 16, 2012 - 08:47 PM
1
2
3
4
5
Total votes: 0
Quote:
I should have specified, global variables. I have placed global variables in a .h at times.
And such a header file can not be included into more than one source file or the linker will emit an error about a multiply defined variable. So, since this file is only included into one source file this should fall under your "rule" about unnecessary header files. You could just as well define that variable in the .c source file.
It all boils down to this: Things that are to be shared between several source files needs to be defined in one of the source files (yes, it could be by way of having it in a header file that just one source file includes). In other source files it must be declared (for a variable this is an extern declaration, for a function this is a function prototype) and this the reasonable approach is to have those declarations in a header file so that the compiler can assert that the definition and the usage does not conflict.
You may do as you wish, and live with the risks of your M.O.. But this had to be said so that C beginners are not led astray when reading this thread.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
And such a header file can not be included into more than one source file or the linker will emit an error about a multiply defined variable.
Just to note that the header protection (#ifndef _ADC_H_) I mentioned above will not protect against this. Imagine this scenario again but with a modified adc.h:
That now has an 'adc_reading' variable definition added. Now, sure, if the programmer used this in main.c:
#include "adc.h"
#include
#include "adc.h"
then there still would be no problem as the re-include protection comes into play so the definition of 'adc_reading' like everything else in the header file is only seen once even if adc.h is included more than once.
However main.c is just one "compilation unit". At the time it is compiled then sure only one copy of adc_reading is created within main.o
The problem comes when you also have a motor_control.c that also does:
#include
#include "adc.h"
...
When this compilation unit is compiled (which could even be the Tuesday after main.c was last compiled) it too will see the contents of adc.h and it too will therefore create an entity called adc_reading in motor_control.o
Finally when the linker comes to join main.o and motor_control.o to make myproject.elf it will find two different adc_reading variables and emit an error about "multiply defined".
That is the reason you should never put anything that generates either variable or function bytes into a .h because it almost inevitably leads to multiple definitions from different compilation units.
I never copied it to a new site so that's a dead link. I now work for the company that wrote that standard, not the company where we used it as our own template so it would now likely violate my contract of employment to distribute a copy - so it's probably as well the link is now dead!
If you want a good standard to work by start with MISRA!
Good explanations. Thanks. It almost works but ..
I'm trying to organize my project this way and realized that I can't externally declare my global register variable :-(
I've tried different combinations of keywords in extern declaration like
gettin' different error messages. What do I do wrong?
There are few files:
//--------main.h
/* not important */
//--------/main.h
//--------extern.h
#ifndef EXTERN_H
#define EXTERN_H
/* Global flags and its bit positions */
extern volatile unsigned char flags; // THE SUBJ
#define flags_KeyPressed_bp 3 //keyboard driver related
/* these two ugly funcs are all I could do to access the subj variable :-( */
void SetGlobalFlag( uint8_t bitpos, uint8_t value );
uint8_t GetGlobalFlag( uint8_t bitpos );
#endif //#ifndef EXTERN_H
//--------/extern.h
//--------main.c
#include "main.h"
#include "extern.h"
//Global flags
register volatile unsigned char flags asm("r7"); //THE SUBJ VARIABLE
// my eerie funcs to handle flags. 'cause I can't get it work with externing :(
// Actually I do not want them here!
void SetGlobalFlag( uint8_t bitpos, uint8_t value ) {
if (value) flags |= (1<<bitpos);
else flags &= ~(1<<bitpos);
}
uint8_t GetGlobalFlag( uint8_t bitpos ) {
return ((flags & (1<<bitpos)) != 0);
}
int main() {...}
//--------/main.c
//--------kbd_drv.h
#ifndef KBD_DRV_H
#define KBD_DRV_H
/***********************************************************************
* here we define macroses to read and set keyboard flag. user can
* change those to put flag wherever he wants.
**********************************************************************/
/* Why these two don't work? (../kbd_drv.c:55: undefined reference to `flags')*/
//#define KEYBOARD_SET_FLAG flags |= (1<<flags_KeyPressed_bp)
//#define KEYPRESSED ((flags & (1<<flags_KeyPressed_bp)) == 0 ? 0 : 1)
/* these two work, but it is not an option to use function call here */
#define KEYBOARD_SET_FLAG SetGlobalFlag(flags_KeyPressed_bp, 1)
#define KEYPRESSED GetGlobalFlag(flags_KeyPressed_bp)
/***********************************************************************
Function definitions
***********************************************************************/
void Keyboard_Driver( void );
#endif //#ifndef KBD_DRV_H
--------/kbd_drv.h
//--------kbd_drv.c
#include "extern.h"
#include "kbd_drv.h"
//perhaps this flag is stored somewhere else. see defines of
// KEYBOARD_SET_FLAG, KEYPRESSED.
//unsigned char kbdPressed = 0; //"Key pressed" flag
void Keyboard_Driver( void ) {
/* something unrelated */
/* Here we have error (../kbd_drv.c:55: undefined reference to `flags')*/
KEYBOARD_SET_FLAG;
/* something unrelated */
}
//--------/kbd_drv.c
One clever book said that "The register declaration can only be applied to automatic variables and to the
formal parameters of a function". But I think if I could define it as external one, there must be a way to declare it as external too, mustn't it?
How could you have a global "register"? When foo.c is compiled the compier might choose to assign R7 to the global. When bar.c is compiled it might choose R13.
If you really want a fixed register in multiple compilation units use:
volatile unsigned char flags asm("r16");
Then also pass -ffixed-16 (or whatever the register number is) to the compiler.
Note however that the library code will NOT have been built with -ffixed-16 so there's every chance it might be using R16 and if you call a library function you may find R16 is corrupted.
To be honest I don't know why you'd do this for "flags" - isn't this why the AVr has GPIOR0/1/2 ?? (obviously use GPIOR0 if you can - especially for bit flags!)
If you really want a fixed register in multiple compilation units use:
volatile unsigned char flags asm("r16");
I use almost the same, but with register keyword. I've tried this very form you shown, and it haven't place var in the register. It uses LDS / STS if there is no register keyword. :(
The compiler really does not use r7 (I use r7 in definition, and use -ffixed-7 in compiler params): I looked for it in listing file - none at all.
But the good thing I've found that if I do not use register keyword in definition then I can declare
useless, of course, because it's about memory location, not register :(
Note however that the library code will NOT have been built with -ffixed-16 so there's every chance it might be using R16 and if you call a library function you may find R16 is corrupted.
it is not a problem. There is no large lib in use, and anyway, I can inspect those libraries for reg usage.
To be honest I don't know why you'd do this for "flags" - isn't this why the AVr has GPIOR0/1/2 ?? (obviously use GPIOR0 if you can - especially for bit flags!)
I asked this mega8 for any GPIORx - no answer.. (and TWI is in use too ).
add:
Also found that if I try to pass 5 pointers to some function, it places them to r16 .. r25 even with -ffixed-16.
Suggest you re-read the thread. The whole point is that you (almost) never name a .c file in a #include
You add the .c that contains routines to be used to the list of files to be compiled/linked. Then you #include the .h that documents the interface to those routines in the other .c files that want to make use of the functions offered.
- Log in or register to post comments
TopTechnically, that is correct. You can have the prototypes in uart.h, the implementations in uart.c w/o #include'ing uart.h, and then #include uart.h in main.c and call the funxtions. The compiler/linker will not complain.
But for me the header files should be seen as specifications of interfaces that both implementors and callers adhere to. Thus they should both include the interface specification.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopDear clawson,
can you please explain bit more about Declaration and Definition, difference b/w them.
As for as my understanding is that memory is allocated in the definition only.
Thanks,
Prabu
- Log in or register to post comments
TopYou have read the entire tutorial / thread haven't you?
But in short:
Declaration: usually found in a .h file - opportunity to make the compiler aware of a function/variable's existence and provide details about the types involved. In the case of a function you can tell it's a declaration because it ends with a semi-colon rather than braces containing statements. In the case of a variable you can tell it's a declaration as it starts with the word 'extern' (you can put the word 'extern' on a function declaration too if you like but don't need to as it's obvious from the fact there's no function body). Declarations (as long as they agree) may occur multiple times. Declarations do not lead to any storage being allocated, they are only to let the compiler (and reader) know about types involved.
Definition: Usually found in a .c file. This is the thing that actually allocates storage and creates something in memory - whether it be the storage to hold a variable or the opcodes that implement a function. A variable definition is obvious by the fact that it does not contain the word 'extern' and a function definition is obvious by the fact that the function header ("prototype") is followed by a statement block contained in braces ({}) which hold the C statements that implement the operation of the function. Definitions must only appear once within all the files passed to the linker and are therefore usually contained in a single .c file.
Example:
- Log in or register to post comments
TopYa i had gone trough the tutorial. It is too good and informative.
what about in the the below code if foo.h is not used?
//foo.c - definition of a variable and function
int n; //will be definition as well as declaration,right?
long my_function(int number, char c) {
return c * number;
}
Thanks,
Prabu
- Log in or register to post comments
TopBoth n and my_function are definitions as well as declarations.
Think of definition as "implementation". Where a variable is actually allocated, or the body of a function is given.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopPersonally I wouldn't confuse myself by calling them both definitions and declarations. Both lead to memory being allocated so, in my book, they are definitions. But clearly, once the compiler has encountered a definition it knows the types involved so I guess in that sense you might also use the term declaration but this seems to be trying to over-complicate something that is really very simple:
Is storage allocated?
yes) it's a definition
no) it's a declaration
- Log in or register to post comments
TopI see your point, Cliff.
For me it is rather like:
A definition is implementing something (and it might lead to memory allocation).
A declaration is about "making the existence of something known" (leading to an entry in the compiler symbol table if the thing is not already there, could lead to an update even if it was already there, and could lead to an entry in the table of unresolved references left to the linker).
A Definition is inherently a declaration.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopAgreed but I think it actually helps the learner to think of them as two distinct things. Declaration=type-info/header(usually), Definition=allocation/C file. Anything more over-complicates and begins to lose the point about where they should be located and why which is the key thing.
- Log in or register to post comments
TopAwesome tutorial. I'm now using the guidelines you explained to manage my project with 11 .c/.h files! Better than having everything in main.c, huh?
Thanks a lot.
- Log in or register to post comments
TopI have a different method of using headers which works out well for me so I thought it might be worth a mention.
Any #define's which are only accessed within the modules .c file, are simply placed at the top of the .c file. Only parts of the module which must be accessed externally go into the .h file. Then all .h files get included into one file called includes.h which is included at the start of every .c file.
I have done some large projects like this, and have never needed to use #ifndef.
Telling yourself something is too hard, or too complicated, is not a determination. It is a decision.
- Log in or register to post comments
TopThis boils down to your header files being the interface to the module and nothing else, which in my view is a beautiful thing.
Wether the defines etc that are needed only inside the volume is placed in the source 'per se' or in another header file is another matter, where my opinions are less strong. But note that a header file will likely be needed for that too, if the 'module' becomes large enough to warrant splitting it's implementation into several .c source files.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopI wish to be able to use fprintf() or fprintf_P() from many different c files in project to send data out via a USART. The problem that arises is the first argument (i.e., FILE *stream) in AVRs w/ multiple USARTS. As a cheat, I would do something like:
in some "global" projDef.h file. com0_str would be declared elsewhere in a "*Msg.c" as
Functions then call like:
The problem is that any file that contains a function that wants to use fprintf() needs to include this projDef.h header file to get to extCom.
I suppose that I could create a header/c file pair that only has one (two) function(s) in it, i.e.,
This c file then would be the only one that reaches out and touches the "com ports". However, this still leads to the problem that every module that includes this submodule would need to know what the two com ports (in a given AVR w/ two ports) are. What is the best solution to this problem?
Science is not consensus. Science is numbers.
- Log in or register to post comments
TopHow is that a "cheat". Defining it in one C file and declaring it extern for the others that need to use IS the right way to do this?!? Not sure the point of your macro though?
- Log in or register to post comments
TopIt is a cheat because my modules are not independent. Meaning, if I have a display.h and display.c file pair whose purpose is to provide an interface to a commercial display, I would like that module to be portable to many projects. However, as soon as I include the fprintf statements, it needs some overarching project definition header file to glue the project together. If I use comExt in one project and comInt in another, I would need to change the code in the display module.
The macro is just to make things neater, to abstract the pass by reference nature of the FILE argument. If I remove the macro, I could put multiple extern definitions of the port in all of my module header files, still only declaring it once (I think). However, I think the naming issue for portability remains.
Science is not consensus. Science is numbers.
- Log in or register to post comments
TopI still don't get your problem? What's wrong with simply doing the equivalent of:
How is that a "cheat". Defining it in one C file and declaring it extern for the others that need to use IS the right way to do this?!? Not sure the point of your macro though?
Here's an example:
- Log in or register to post comments
TopThe only problem is that second.c relies on the variable being declared as uart_str in some other file. If second.c gets reused in another project that defined it as uart0_str or uart1_str, second.c would need to be changed. Maybe this is unavoidable.
Science is not consensus. Science is numbers.
- Log in or register to post comments
TopI cannot see a way to avoid it - the object has to be instantiated somewhere. Perhaps the "client" should be told to own it? They actually define it in their main.c (or whatever).
Having said that surely the FILE used for uart_str would be located with UART_init, UART_putchar() and others in uart.c and a lcd_str would be created with LCD_init(), LCD_putchar() and so on in lcd.c ?
That is:
- Log in or register to post comments
TopThanks for the advice. My setup is currently as in your example.
I think there was a miscommunication regarding the "str" for the LCD. The display module (used as an example here, really I meant any module) does not itself communicate via a UART. It uses some other interface (i.e., I2C or SPI). I want the display module to be able to print informational messages out the "external" uart to be monitored by some third party -- there is only one uart_str.
Science is not consensus. Science is numbers.
- Log in or register to post comments
TopIf you want the output of a module to be more universal, then the module could contain a FILE* which either gets loaded directly by main, or via a function.
Telling yourself something is too hard, or too complicated, is not a determination. It is a decision.
- Log in or register to post comments
TopThe tutorial is very good - I used similar modules in a project containing about 40 source files.
A small hint to improve the source readability:
Use a template for your .c and .h files.
The example below is for a smaller project, a controller for a brushless DC motor. It includes comments for Doxygen. The template.h is similar
- Log in or register to post comments
TopWhere do you put the module related header files?
Like for example my uart.c needs avr/io.h, avr/pgmspace.h etc. where should I put it? In the uart.h or in the uart.c?
I know that uart.h should be included in uart.c so even if I put the other header files in the uart.h it will be included in uart.c
So which version do you prefer? Putting the includes in the module header file, or in the source file?
- Log in or register to post comments
TopTry to keep header files as local as possible to what they document. Not everyone who includes your uart.h necessarily wants an inclusion of avr/io.h and especially avr/pgmspace.h forced upon them.
What you can do is use those files own header protection to give warnings about their requirement. Say your uart.h uses types such as uint8_t which are indirectly defined by the inclusion of avr/io.h you could rely on the fact that the io.h has this:
So in your own header file you could include:
If the user then uses:
they would get that compilation error. While:
would work just fine.
- Log in or register to post comments
TopI generally don't use header files, I just declare everything (relating to that module) at the top of each code module. Seems quicker from an editing point of view and reduces the number of files involved.
But I frequently have to put #include et al at the top of each code module. Is there a danger in having the same header file appear multiple times like this at the top of multiple modules.
I use:
AS6 (under duress)
WinAvr 20100110
Windows 10
STK 600
AVR ONE!(broken and Atmel won't fix)
JTAGICE3 (only works with AS6)
AVRISP II
So far - '88 '2560
Sometimes my own RTOS
- Log in or register to post comments
TopThose comments seem to suggest you really haven't got the concept of header files. The #include basically just pastes the included file into the file that has the #include - no magic. Consider the instance where you #include that file into another file that has already #included the
- Log in or register to post comments
TopI used to use them all the time for larger projects, but I find that with smaller MCU code, I would rather have the function declarations and variable definitions at the top of the .c module than having a separate file open. Just laziness more than anything else.
My question is if I have a program comprised of three .c modules and each of them have a io.h (or any other include) file included at the top, is there any danger? The compiler does not complain. Actually it will not compile if I don't do it. I could make a foo.h to go with my foo.c and put the io.h file inside the foo.h but that seems pointless.
I use:
AS6 (under duress)
WinAvr 20100110
Windows 10
STK 600
AVR ONE!(broken and Atmel won't fix)
JTAGICE3 (only works with AS6)
AVRISP II
So far - '88 '2560
Sometimes my own RTOS
- Log in or register to post comments
TopRegards,
Steve A.
The Board helps those that help themselves.
- Log in or register to post comments
TopAnd even more so the concepts of function prototypes, typedefs and extern declarations.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopIndeed. Suppose you have an adc.c that contains:
Now in main.c you want to call those functions. How on earth can you achieve that? How can the compiler know when it encounters a call to:
what the input or return parameter types are? This is the whole reason you would have adc.h:
It would be #include'd in main.c so the compiler knows what the interface to each of the routines is. This is pretty fundamental to the use of the C programming language, ignore it at your peril.
- Log in or register to post comments
TopI believe that it is important for the understanding of this to keep the concepts of prototypes, typedefs and externals apart from the concept of the #include mechanism as such. Together they form a powerful mechanism for structuring projects on the source file level, but taking them apart will reveal what is actually going on and helps understanding what this is all about.
As short as I can manage:
Using Cliffs example, suppose you have functions for handling the ADC in a separate source file adc.c, but you want to call these functions from another source file, say main.c . Now purely technically you might get away without having any prototypes in adc.h but just the definitions (implementations) of the functions. In main.c you definitively must have prototypes for the functions, or else (as Cliff points out) the compiler will not know about parameter and return types etc.
But (and that is a big BUT): If you at some time change the actual definitions (implementations) of the functions in adc.c, but fail to update the prototypes in main.c the result will likely be disastrous. Since the compiler actually compiles each C source file separately it will not spot the mismatch. The linker will then happily resolve the calls from main.c to functions in adc.c – but since the code from main.c will push different parameters from what the code from adc.c expects everything will be a mess. You will not get any build errors, but you application will likelt crash at run time.
The solution is to make sure that the very same prototypes are seen in both adc.c and main.c. I am not speaking about two prototypes that look identical (because, again, with time one of them will change but not the other). I am talking about the two source files actually “seeing†the same prototype. The solution is to place such prototypes in a text file that is then inserted into both source files just before compilation proper takes place. This is what header files and the #include pre-processor directive is all about.
Now when you change an implementation in adc.c but fail to change the corresponding prototype in adc.h, the compiler will emit an error when compiling adc.c. You now change the prototype, but fail to change the actual call (e.g. adding a newly introduced parameter) in main.c – and the compiler will emit an error compiling main.c. When that also is corrected the application builds clean.
Think of an include file as a contract between the supplier (implementation) and consumer (caller) of some functionality. Both ends must “do the same thing†or you will get a build error. Without that contract you will get a runtime error. A build error is always preferable to a runtime error.
I cannot see how you can get around this if you have several source files. If you actually have your prototypes only in main.c and implementations in adc.c, then you need to rethink and take in what I describe above. Effectively, you are satisfying the compilers need for knowing how to call the functions, but lose out on the advantages you can get from a common include file. Ignoring this will lead to disaster sooner or later. Probably sooner..
Not so short after all, but I hope it helps to clear up what this is really about.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopGuys, my original question was:
"Is there a danger in having the same header file appear multiple times like this at the top of multiple modules." Like io.h.
I do use a .h file if I find I want to put all the prototypes and variable declarations in one place. Sometimes. Most of the time they are at the top of my main source code module. If I want to re-use a bunch of stuff then I create a .h file for the module so I don't have to do much work the next time around.
I do use typedefs when I want to get a bit more portable.
I understand and use extern when needed.
I just asked what was going to happen if I put #include io.h at the top of each c module to make the compiler happy.
I do appreciate the extention of the tutorial but to extrapolate from my original question and statement that I prefer to put everything at the top rather than a separate .h file means I lack a bunch of understanding was a touch pedantic and condecending, don't you think?
I use:
AS6 (under duress)
WinAvr 20100110
Windows 10
STK 600
AVR ONE!(broken and Atmel won't fix)
JTAGICE3 (only works with AS6)
AVRISP II
So far - '88 '2560
Sometimes my own RTOS
- Log in or register to post comments
TopI may have a module called read_gps.c
I call it and it returns a variable.
My main module would have the prototype for read_gps(xxx) But the read_gps.c module may have 50 functions to do its work. And all 50 functions may have their prototypes at the top of that code module.
Why is that a sin?
I don't and won't ever need to call any of those internal functions from anywhere else. I can make a single read_gps.h file and include the prototype for the read_gps(xxx) but that is just as much work or more than putting the prototype along with the others at the top of the main module.
I can put all the prototypes for the internal read_gps.c file in read_gps.h but then I would have to include it in two places to get the compiler to work.
I can have two .h files, one containing the read_gps(xxx) prototype to include in the main module and another containing all the internal module protypes to include inside the read_gps.c module but that is just for housekeeping. In this case I see no added value of header files.
I use:
AS6 (under duress)
WinAvr 20100110
Windows 10
STK 600
AVR ONE!(broken and Atmel won't fix)
JTAGICE3 (only works with AS6)
AVRISP II
So far - '88 '2560
Sometimes my own RTOS
- Log in or register to post comments
TopExtrapolationg, you said? For functions that are both defined in and called from one and the same source file you do not need to have prototypes in a separate header file. I never said that.
I wasn't my meaning to be condecending. Every time one answers, one has to make some assumption of the knowledge and skill level of the intended receivers/readers. If I missed the mark widely this time, I did that. Period.
OTOH, when you're saying
it seems to me that you've missed the point. The prototype for read_gps() should be seen in two source files, not only in the main module. If you actually type it into both files then i) this will be un-necessary work, and ii) it will not in any way "guarantee the contract".
Nothing bad, since that header file is nicely written and following good conventions. The compiler will use the parts of it that it needs, and the rest of the stuf in it will not be used.
I am a bit uncertain what is meant by "variable declarations" above, but if it is something like
then this will spell problems when the header file in inluded into more than one source file. The root of the problem isn't the inclusion into two source files, but having the variable definition in the header file. They should go into .c source files just like function implementations.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopSorry, very importantly above my example for adc.h SHOULD have said:
If you look at any "standard" header file such as those within the AVR-LibC collection you will see they all have protection like this. If main.c then said (in error):
or perhaps more likely
then on the first inclusion of adc.h the _ADC_H_ define is not made so the bit between #ifndef and #endif is used. This introduces all the types/interfaces and, inportantly now #define's _ADC_H_.
Now when it gets to the second (perhaps indirect) #include "adc.h" the _ADC_H_ symbol is already defined so the entire section between #ifndef and #endif is ignored this and all subsequent times.
THAT is the way you ensure that it doesn't matter if there are multiple inclusions of a .h file.
EDIT: BTW just looked at the universally used and guess what...:
PS the annoying thing is that I even realised I'd forgotten to mention the header protection thing when I was sat in the local health centre having an ECG for a suspected heart attack (luckily not it turns out) but I was only just allowed back near a PC just now by she who must be obeyed.
- Log in or register to post comments
TopSorry, was not directed at you. The initial reply to my initial question didn't answer my question but did question my understanding.
I should have specified, global variables. I have placed global variables in a .h at times. Most of the time my .h files just have function prototypes, defines and typedefs. But now-a-days, I don't use many .h files. I just put it all in the code.
I use:
AS6 (under duress)
WinAvr 20100110
Windows 10
STK 600
AVR ONE!(broken and Atmel won't fix)
JTAGICE3 (only works with AS6)
AVRISP II
So far - '88 '2560
Sometimes my own RTOS
- Log in or register to post comments
TopAnd such a header file can not be included into more than one source file or the linker will emit an error about a multiply defined variable. So, since this file is only included into one source file this should fall under your "rule" about unnecessary header files. You could just as well define that variable in the .c source file.
It all boils down to this: Things that are to be shared between several source files needs to be defined in one of the source files (yes, it could be by way of having it in a header file that just one source file includes). In other source files it must be declared (for a variable this is an extern declaration, for a function this is a function prototype) and this the reasonable approach is to have those declarations in a header file so that the compiler can assert that the definition and the usage does not conflict.
You may do as you wish, and live with the risks of your M.O.. But this had to be said so that C beginners are not led astray when reading this thread.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopJust to note that the header protection (#ifndef _ADC_H_) I mentioned above will not protect against this. Imagine this scenario again but with a modified adc.h:
That now has an 'adc_reading' variable definition added. Now, sure, if the programmer used this in main.c:
then there still would be no problem as the re-include protection comes into play so the definition of 'adc_reading' like everything else in the header file is only seen once even if adc.h is included more than once.
However main.c is just one "compilation unit". At the time it is compiled then sure only one copy of adc_reading is created within main.o
The problem comes when you also have a motor_control.c that also does:
When this compilation unit is compiled (which could even be the Tuesday after main.c was last compiled) it too will see the contents of adc.h and it too will therefore create an entity called adc_reading in motor_control.o
Finally when the linker comes to join main.o and motor_control.o to make myproject.elf it will find two different adc_reading variables and emit an error about "multiply defined".
That is the reason you should never put anything that generates either variable or function bytes into a .h because it almost inevitably leads to multiple definitions from different compilation units.
- Log in or register to post comments
TopI have not yet read through all this whole topic.
And it seems there is nothing further mentioned about the
contents of cs.html.
The http://www.ourcottage.plus.com/c... is closed.
So could anyone give a new link or add an attachment?
Thanks ahead. :D
Andy Liu
- Log in or register to post comments
TopI never copied it to a new site so that's a dead link. I now work for the company that wrote that standard, not the company where we used it as our own template so it would now likely violate my contract of employment to distribute a copy - so it's probably as well the link is now dead!
If you want a good standard to work by start with MISRA!
Also read "Writing Solid Code" my Steve Maguire.
- Log in or register to post comments
TopAnywany,thanks cliff. :D
Andy Liu
- Log in or register to post comments
TopGood explanations. Thanks. It almost works but ..
I'm trying to organize my project this way and realized that I can't externally declare my global register variable :-(
I've tried different combinations of keywords in extern declaration like
gettin' different error messages. What do I do wrong?
There are few files:
One clever book said that "The register declaration can only be applied to automatic variables and to the
formal parameters of a function". But I think if I could define it as external one, there must be a way to declare it as external too, mustn't it?
- Log in or register to post comments
TopHow could you have a global "register"? When foo.c is compiled the compier might choose to assign R7 to the global. When bar.c is compiled it might choose R13.
If you really want a fixed register in multiple compilation units use:
Then also pass -ffixed-16 (or whatever the register number is) to the compiler.
Note however that the library code will NOT have been built with -ffixed-16 so there's every chance it might be using R16 and if you call a library function you may find R16 is corrupted.
To be honest I don't know why you'd do this for "flags" - isn't this why the AVr has GPIOR0/1/2 ?? (obviously use GPIOR0 if you can - especially for bit flags!)
- Log in or register to post comments
TopI think you are probably in a minority of one, there!
Top Tips:
- Log in or register to post comments
TopI use almost the same, but with register keyword. I've tried this very form you shown, and it haven't place var in the register. It uses LDS / STS if there is no register keyword. :(
The compiler really does not use r7 (I use r7 in definition, and use -ffixed-7 in compiler params): I looked for it in listing file - none at all.
But the good thing I've found that if I do not use register keyword in definition then I can declare
with no errors! :-)
useless, of course, because it's about memory location, not register :(
it is not a problem. There is no large lib in use, and anyway, I can inspect those libraries for reg usage.
I asked this mega8 for any GPIORx - no answer.. (and TWI is in use too ).
add:
Also found that if I try to pass 5 pointers to some function, it places them to r16 .. r25 even with -ffixed-16.
- Log in or register to post comments
TopIt's an old article, but it has really helped me a lot. I really appreciate you.
AVR, ARM, MFC, .NET
- Log in or register to post comments
TopPages