Hi Freaks! Time for another half-baked tutorial! This one will focus on how to split up your C projects into manageable files (modules). It's by no means definitive, and serves as only a guide.

There comes a time when a project has outgrown the scope of a single file. Perhaps it's the point at with you need to add more RAM to your computer just to open your project, or when you realize you've just spent 45 minutes tracking down the timeout function you swore you wrote two weeks ago. Whatever the reason, it's time to split your project up into several manageable files, which you can then keep better track of. This tutorial will give several pointers about the intricacies of how to accomplish such a task.

Step one - identify common routines

First of all, it makes sense to group all the common routines into their own files - eg. one for USART management, one for your protocol layer handler, one for your main code. You should determine which functions can be moved into a separate files while still retaining some connection with one another. Let's take the following example of routines:

We can split these routines up into several small files - one for the USART, one for the main (and misc) routines, one for the speaker and one for the ADC (and related processing).

Let's take a look at our proposed new structure:

USART.c

SetupUSART()
EnableUSART()
GetUSARTByte()
ProcessByte()

Speaker.c

SetupSpeaker()
Beep()

ADC.c

CheckADCChanel()
CheckTempSensorVal()

Main.c

main()
SleepMode()
TurnOnStatusLed()
TurnOffStatusLed()

Ok, looks pretty good! We'll cut and paste those routines into the appropriate files in the same project directory, so now we have a bunch of C files containing related functions.

Adding the new files to your makefile

Even though you've made no functional changes to your code outside moving certain routines to a different file, you still need to tell the compiler, linker and associated GCC tools where everything is now located. Open up your makefile, and you should find some lines similar to the following (if your makefile is based off the WinAVR template):

What we now need to do is add the file names of the newly created files. We'll take our above example here again for consistency. Our new extra files are called "ADC.c", "Speaker.c" and "USART.c", so we need to add those to the SRC line of the makefile.

Now, that'll work, but it's a real pain for future expansion. To make our life easier, we'll place the filenames on their own line in alphabetical order. To indicate a line continuation in a makefile, we need to place a "\" at the end of the continued lines:

NB: Watch the file case! To GCC and its related utilities, "MAIN.C" is not the same as "Main.c". Make sure you put down the file names in the exact same case as they appear inside explorer, or you'll get build errors!

Naming the routines

One problem with our multi-file setup remains; routines are still hard to find across the files. One might easily identify the file location of our mythical "CheckADCChanel()" routine, but what about "SleepMode()"? Obviously a naming convention becomes important.

Now, this is where it gets tricky. There's really no set standard for function names, and every one prefers something different. It is important to choose which one you prefer, but it is ten times more important to remain consistent in your scheme across your entire project.

The first word, symbol or acronym in your function name should indicate the file it is located in. For example, all the ADC functions will have "ADC" at their start, and all the speaker-related functions in Speaker.c would have "Speaker" at their start. You can eliminate repetition in a name as it becomes self-explanatory what the function is referring to due to the prefix - thus "CheckADCChanel()" would become "ADCCheckChannel()" (or similar), rather than the superfluous "ADCCheckADCChanel()".

I'll use our example again and put here a possible function naming scheme. Note that the "main()" function's name remains unchanged as it is mandated by the C standard:

USART.c

USARTSetup()
USARTEnable()
USARTGetByte()
USARTProcessByte()

Speaker.c

SpeakerSetup()
SpeakerBeep()

ADC.c

ADCCheckChanel()
ADCCheckTempSensorVal()

Main.c

main()
MainSleepMode()
MainTurnOnStatusLed()
MainTurnOffStatusLed()

This new scheme makes finding the location of a routine quick and easy, without the need for a multi-file search utility. Don't forget to change the function prototypes in your header file to the match your new function names!

Making functions static

Static functions is possibly something you've never heard of up to now. The process of declaring a function to be static indicates to the compiler that its scope is limited to the source file in which it is contained - in essence it makes the function private, only accessible by other function in the same C file. This is good practice from two standpoints; one, it prevents outside code from calling module-internal functions (and reduces the number of functions exposed by the file) and two, it gives the compiler a better chance to optimize the function in a better way that if it was assumed to be able to be called by any other source file.

Identify which of your functions are module-internal, and add in the static keyword. In our example, let's say that the "USARTEnable()" function was only called by "USARTSetup()", and never by any other source file. Assume that the USARTEnable function is declared as the following:

void USARTSetup(void)

We'll make the function static to reduce its scope to inside USART.c:

static void USARTEnable(void)

Note that the static keyword should be added to both the prototype in the header file, as well as to the function in the C source file.

Global variables

Your project probably has quite a few global variables declared at the top of your main source file. You need to cut-and-paste them each into the most appropriate source file. Don't worry if it's referenced by more than one file; dealing with that case will be handled later in the tutorial. For now, just put it in the C file you deem to be the best for it.

Just in case you've done this, remember the following golden rule: header files should declare, not define. A header file should not itself result directly in generated code - it is there to help the compiler and yourself link together your C code, located in C files. If you've put any globals inside your header file, move them out now.

Splitting the header file

This is where the hard part begins. So far we've successfully split up the contents of our project into several C files, but we're still stuck with one large header file containing all our definitions. We need to break our header file up into separate files for each of our C modules.

First, we'll create a bunch of .h header files of the same names as our .c files. Next, we'll move the obvious things from the master header file, the function prototypes. Copy each of the prototypes into the respective header files.

Next, the macros. Again, move the macros into the header file where they are used the most. If you have any generic macros that are used in the majority of your source files, create a new "GlobalDefinitions.h" header file and place them there. Do the same for any typedefs you may have in your header file.

Let's assume our above example has the following original header file:

Pretty straightforward - using our renamed functions, the job becomes easy. The only issue is the orphaned macro "BitMask", which we'll assume is used by all the files. As discussed, we'll place that into a separate header file called "GlobalDefinitions.h".

Renaming the macros

As with the function names, the macros should also be renamed to indicate where they are located. Again, use whatever convention you prefer.

Global variables revisited

Now comes the time to fix up those global variable references from before. You're faced with a problem; your global variable is declared in one file, but it's used in two or more. How do you tell the other files to use the declaration you already made?

The answer is the use of the "extern" keyword. This keyword indicates to the compiler that a global of the specified name and type has been declared elsewhere, and so the references are fixed up by the linker when the project is built. Inside the header file of the C module containing the global, add the same line of code (sans any initialization value) but add the extern keyword. Say we have the following:

USART.c

unsigned char LastCommand = 0x00;

We can add a reference to the global in USART.h to make it visible in our other C modules:

USART.h

extern unsigned char LastCommand;

Do this for each of your global variables that are accessed in C files other than the one in which it is contained.

Including the header files

Our final task is to link our header files to the relevant C files. Firstly, each .c file should include its own header file. In the C language, for header files located in the project's current directory, we use quotes around the file names:

USART.c

#include "USART.h"

Speaker.c

#include "Speaker.h"

ADC.c

#include "ADC.h"

Main.c

#include "Main.h"

Next, we need to include the library header files relevant to each C module. For example, our "Main.c" and "Speaker.c" files both make use of the "avr/io.h" header files. System headers should have angled brackets instead of quotes:

Speaker.h

#include

Main.h

#include

Rinse and repeat for each of the required system header files inside the header of each C module.

The last task of this step is to include the header files used by each module. For example, if a function in Main.c calls a function in ADC.c, we need our Main.h header file to include the ADC.h header file.

Final step - header file protection

The last thing to do before our conversion is complete, is to protect our header files from multiple inclusion. Take the following example. Say that Main and ADC both refer to each other:

Main.h

#include "ADC.h"

ADC.h

#include "Main.h"

What happens when this is compiled? The preprocessor will look at Main.h, then include ADC.h. However, ADC.h includes Main.h, which again includes ADC.h, etc...

To guard against this problem, we can use preprocessor defines. The following code snippet is the basic protection setup:

#ifndef MAIN_H
#define MAIN_H
// Header file contents
#endif

This construct, when applied to each of your header files, will protect against multiple inclusions. As each C file is compiled, the associated header file is included, as well as any other referenced header files (via includes in the C file's header file). As each header is included, a check is performed to see if the header's unique token is already defined, and if so the inclusion halts to prevent recursion. If the token is not already defined, the preprocessor defines it and looks at the remainder of the header file's contents. By giving each header file a different token (typically the header's filename in ALL CAPS, and the period replaced by an underscore), this system will prevent any preprocessor troubles.

Let's take a final look at how our mythical C file's headers might look like:

Identify which of your functions are module-internal, and add in the static keyword. In our example, let's say that the "USARTEnable()" function was only called by "USARTSetup()", an never by any other source file. Assume that the USARTEnable function is declared as the following:

Anyone who doesn’t know C will greatly benefit form your tutorial and the rest of us wish we had a tut like this when we first started learning C.
Very well written and concise, great job!
Keep up the good work.
Cheers
John

I have to second John's statement. I'm going back through my code with tutorial in-hand to see if there are areas where I can clean things up and make it more readable.

I like the idea of using the .c filename as the prefix for each of the routines inside that file. I know I don't do that 100% of the time, but it's a nice convention and I plan on using it from now on.

Thanks for the comments John and Tom. This is why I write these tutorials!

Tom: The function naming convention is up to you, but I DO strongly suggest you follow one. Use whatever you think is best, but be consistent and do make some reference to where the function is stored.

In my project, I use {ABBR}_{FNAME}, where "{ABBR}" is an abbreviation - actually acronym - of the file name. This means that a function "DoStuff" inside "SomeAmazingCFunctions.c" would be named "SACF_DoStuff". Use whatever works for you.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

Header files should NEVER directly output code when included - it's a bad idea all round. You might end up with naming conflicts, duplicated functions, etc and it's just a bad practice all round, just like including C files. Follow my guide here and you'll have a manageable large project which follows basic standards about multiple files.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

What happens when you want to #include the same .h file into two different .c files?

Remember that, in general, each .c file in a project is passed to the compiler and compiled in isolation. So if file1.c includes shared.h and that shared.h actually generates any code or data then file1.o will include a copy. Now you compile file2.c which also includes shared.h and the output file2.o ALSO now has copies of the generated data and functions. Hopefully the linker will recognise things as being identical but the chaces are you are going to get "xxxx is mutiply defined" errors during the link.

Cliff

PS I was about to point you towards an excellent tutorial about code modularity in the Tutorial Forum that explains how to do this properly - THEN I realised I was actually typing on the end of it! (obviously more caffeine needed here)

last night i made it the same way as you mentioned above,but now the big problem appears! avrstudio4.13 tell me that "gcc plug-in:Error:Object file not found on the expected location ..."i have repaired my gcc and avrstudio4,but there is no help.what the hell is happening???

cliff:
It's OK now. I fortunately found it out. Never used this kind of program structuring before. I've also had a problem, that the ADC part will be trying to use some of the USART code. It gave me an unknown reference. Is including the "usart.h" everywhere where it is needed the right way, or should there be one file with all of the function prototypes?

There are pointy haired bald people. Time flies when you have a bad prescaler selected.

Yes, the "right" way is to include all the required header files. If you've structured your project as this tutorial teaches, including the header files should do nothing more than expose typedefs, enums, macros, prototypes and variable declarations - no code size penalty. If you *really* want, you can make public and private headers for each file, with only the items that need to be globally exposed in the public headers.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

If you *really* want, you can make public and private headers for each file, with only the items that need to be globally exposed in the public headers.

I've sometimes wondered if I should be doing this. But how would one keep the private header private? Simply not mention it in documentation? Or add a big comment "Should only be included in foo.c"? Splitting things that are only needed in one file to another file 'feels' wrong even though it would follow the rule that declarations go to header files.

So I usually put declarations of static functions and constants only needed in one place to the top of the corresponding .c file. I would appreciate any advice or comments others may have on this.

In our large projects a module will generally have a three letter acronym (e.g. SPI) and in the \spi directory there will be various spi???.c files, an spi.h that is the "public" header file that may be #include'd by other modules or main code in the project then any .h stuff that other modules don't need to see will go into spii.h (the added i for "internal"). While the tla???.c files will probably include tla.h and tlai.h, outside of that directory the C files will only include tla.h (they may know that tlai.h exists but would never use it directly)

Hi All,
Again a great tutorial here.
Where should I best store these new source and header files in Winavr ?
Where to configure the path to these files ?
Do I have to configere the path ones ?
Or do I have to add Header and Source files in the left
column named "AVR GCC" in AvrStudio for each new project that needs these files ?
Thanks,

Where should I best store these new source and header files in Winavr ?
Where to configure the path to these files ?
Do I have to configere the path ones ?
Or do I have to add Header and Source files in the left
column named "AVR GCC" in AvrStudio for each new project that needs these files ?

I don't have much experience in using AVRStudio as a GCC frontend, so the following is only what I believe to be the case. I'm sure someone else will correct me if I get things wrong.

You should put your source files in the same directory as your main project source file, to keep things neat and ordered. You should then add them to the left AVRStudio source file pane, to tell AVRStudio to compile and link them in with your main source file.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

Where should I best store these new source and header files in Winavr ?
Where to configure the path to these files ?
Do I have to configere the path ones ?
Or do I have to add Header and Source files in the left
column named "AVR GCC" in AvrStudio for each new project that needs these files ?

[...]You should put your source files in the same directory as your main project source file, to keep things neat and ordered. You should then add them to the left AVRStudio source file pane, to tell AVRStudio to compile and link them in with your main source file.

Right click on 'Source files' -> 'Add existing source file(s)' to do this and add all .c files.

Then add the #include statements for the corresponding .h files on the top of your main source file.

Note: C doesn’t support the concept of a module global, this naming convention allows the
distinction between a system global which would be used by other modules from a module
global which should not be accessed by other modules

Isnt it so that making a module level variable static means its global to module level and inaccessible from other modules?

For that matter, not declaring the variable in the modules header file will generate an 'undeclared ...' warning when it is used from outside the module. And we always want zero warnings right? :)

However, I'd recommend against it. Generally, it's considered good practice to go with the normal one header per source file route. That way each source file only includes what is needed, preventing multiple definition problems and speeding up compilation.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

[...]go with the normal one header per source file route. That way each source file only includes what is needed, preventing multiple definition problems and speeding up compilation.

And apart fromthose two (valid) points, ponder this: What happends when you want to take one piece of the developed source code and use in another project. Example: Some code to handle a "ring buffer" "on top" of the UART, or maybe some code to handle a LCD display. If all your prototypes are in one big header file you now have to copy the parts you want and paste them into another header file for the new project. If you had a separate RingBuffer.h or LCD.h (to accompany your RingBuffer.c or LCD.c) you'd just make a copy of the files to the new project.

And after doing that for a while you get problems with those copies drifting apart leading to eg. bugs fixed in one project being un-fixed in another. You realise that you need those files stored in one master place. Every time you fix a bug or make an enhancement you'd update the master files, test them and then distribute them to all projects that are using them.

(And after doing that for a while you'd stop distributing the sources to the different projects and instead build librarys of precompiled code to distribute. Or you might set up your own version control system, eg. Subversion and store the files there...)

Anyhow, my point is - it's not only about compiler efficiency and avoiding build errors. Its just as much about making code reuse easy, efficient and less error-prone.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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 don't have a .h file for every .c file but one .h file for every "module" that may actually contain a number of .c files. So I might have ADC support in a single adc.c with a corresponding adc.h but for something like a flash filing system there could be 10 or more .c files and a single ffs.h

I've been working on a project for uni and have been putting all my code into the one .c file and the one .h file.

However, it was all getting a bit messy, so I decided to try and break it all up into seperate .c and .h files for ease of documentation.

However, I'm now getting an issue when I try and compile.
I get messages such as

../ISR.c:13: In function '__vector_6':
../ISR.c:31: error: 'distance_string' undeclared (first use in this function)

'distance_string' is declared in another header file (distance_measure.h) with the 'extern' keyword, so I don't understand why AVR Studio isn't linking it correctly. Do I have to include distance_measure.h in isr.h? Through reading Dean's tutorial it makes it sound like I only do this if I am calling a function from another file.

Can anyone help me out with some ideas to try?
If I need to post the code I will, it's just that it's all a bit messy at the moment :wink:

I would like to add a tip that will save you a lot of time in Programmers Notepad. There is an easy way to prepend extern to long lists of declarations:

1)Make a vertical list of the word "extern " (note the space character) on the left margin using copy and paste
2)Hold down the Alt key and click and drag a box around the list you just made. The list should be selected now.
3)Cut
4)Place the cursor at the beginning of the list of declarations
5)Paste

If you do this, PN should have prepended your declarations with "extern ". I hope this is helpful to someone.

edit: I just figured out that it works in AVR Studio also, only you have to continue holding Alt until after you cut. And also you have to issue the cut command with the mouse not the keyboard.

We see questions similar to this on and off here at 'freaks, and what you really need to know to analyze the situation yourself (rather than us just giving a cook-book recipe for resolving it) is that all includes are handled by the preprocessor before the compiler proper starts looking at the source. Wherever an #include is done, in that place the whole header file is inserted into the source code (and nested includes work that way too). So when the compiler proper starts working there are no #includes left in the "compilation unit".

Now, in your ISR.c, on line 31, the declaration of distance_string must aready have been seen by the compiler.

If you are really curious there is a switch to the gcc compiler to produce a listing file which shows what the compiler proper sees after the preprocessor has "mangled" the file. I don't recall the syntax of the switch - go to the (avr-)gcc documentation if you really want to try it out.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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]

The "undefined reference to X" is probably because the source file that actually defines (implements) X is not included in the project. While compiling, the compiler only sees

extern type X

and goes "Oh, allright it is somewhere, but I don't know where. Another instance of me the compiler will see it while compiling some other source file, and we both will leave it to the linker to resolve this." As that other file never is compiled the linker will not see it and goes "Darn, here's a reference that I cannot resolve".

When you remove all those extern from the declarations they all turn into definitions (implementations) of X. Now every time the compiler sees one of those it will emit code for it into the object file. And when the linker gets hold a hold of thyose object files it has to emit an error becuse it sees the same variable implemented several times.

The solution to the first problem is not to delete all "extern" thingies, but to locate the source file that actually implements X and see to it that it gets compiled and linked in.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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]

Im not sure if this may help but, one may also use function table in declaring functions, specially those that almost have the same characteristics (ie communication protocols that sends, receives data).

I'm just re-organising a large project, but I've got some problems with global vars.

this is my situation:
I've got several source files with their headers
main(.c .h) UART(.c.h) EEPROM(.c .h) ...
I've got a Constants.h with some defines that are used in the whole project and need to be included everywhere, as th GlobalHeader.h where i put some type defs and library includes.

1) those headers that go everywhere stay better in c files or in every header? (i.e. changes something if I put Constants.h in main.c or main.h etc...)

2) I've got a compilation error (undeclared variable) on global vars. I've got some global (whole project) vars which I declared at the beginning of the main.c as

uint8_t checkSend;

and in the main.h as

extern uint8_t checkSend;

now I got errors compiling UART.c whic uses those global vars. Do I need to put the extern uint8_t checkSend; in headers of every file wich uses this var?

* Include as FEW header files in other files as far as is possible for several reasons:

(1) You can quickly tell what modules are **really** dependant on other modules.

(2) Compile time. OK, AVR compile time is relatively short, but wait until you do a complex C++ project using lots and lots of template functions. You'll definitely appreciate this rule then!

* Include the header files in order of custom.h through to the standard libraries. You'll have less dependency problems when porting the sources to something else.

When separating out functionality, I usually group related files in a directory. It then makes it very easy to branch this directory into another project and track/merge changes between the two of them. See comments on a source control system below :)

And, not directly related to C programming (so I expect to get flamed), but I strongly recommend the following:

(a) Learn C++, or a reasonably close-to-metal Object-oriented Language, even if it's for doing basic host-side work. My C code (and even assembly!) is cleaner, more portable and far more maintainable after learning an OO language and putting various practices in place.

(b) There is no excuse whatsoever (and I really, really mean that) for not using a version control system. Even if you're an only-programmer or hobbyist on a project. One day, you'll break something and wonder what you did to break it.

Subversion is free, open source and cross-platform, both command line and graphical for Windows and *nix.

(c) C99 includes nice features like inline, restrict and const that, when used correctly, will make code safer and faster in many scenarios.

Subversion is free, open source and cross-platform, both command line and graphical for Windows and *nix.

Agree and if using Windows then Tortoise is a nice interface. But if you are in Linux also consider Git which is the new pretender to the SVN crown (possibly because it was written by Linus Torvalds with the needs of version managing the Linux kernel in mind)

I'd say that there is a troika of contenders: Bazaar, Git and Mercurial. There are Windows Explorer-integrated GUIs available for all three (TortoiseBzr, TortoiseGit and TortoiseHg).

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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 have used this tutorial as a basis for splitting up my code for larger projects, however my compiler (GCC) is grumpy and coming up with the following warnings regarding the static function declarations:

The function definition is definitely in the .c file with a declaration in the .h file.

If need be I can include the full code, however I get this with all of my static functions and do not think it is necessary.

Does anyone know what this warning is about? I have searched for a list of warnings, but have had little success. I obviously prefer to not have any warnings, even if they are not hazardous to the codes execution.

I would like to find out more about the compiler warnings, for future reference, as in a complete list of warnings and there meanings. As well as a work around for this problem.

I suppose you are including the header file into more than one source file, but only define (implement) the static function in one of them.

If the function is static, this means that it is only visible inside the source file where it is defined, and thus it's function prototype needs not be in the header file at all. For me the primary reason for header files is tha they are "contracts" between proucers and consumers of eg functions. In your case the producer and the consumer is the same source file, so the contract can be in that file itself.

You can of-course place such a prototype in a header file, but you will need a separate such heaer file for each source file that declares static functions.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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]

What we do for any given module TLA is to have both a tla.h which is Johan's public "contract" and also a tlai.h (i=internal) which is a private header file for information that only needs to be used amongst the components of the module. However we wouldn't put a static function declaration into even the tlai.h. The thole point of "static" is that they are private to the one .c file where they are defined so if the function needs to be announced before it is used a simple declaration would be made within the early sections of the .c

spliting is very nice idea, as one said you'll especially benefit when using OO languages. The disadvantage is that with separate compilations compiler has much less oportunities to optimize program. For example (AFAIK) it doesn't inline code compiled in other module, it pushes more registers then needed or just leaves unused functions in generated header. Therefore after such spliting user usually should be more compilator-aware - for example ISR that call function should be in same module - function we'll be inlined, or at least only needed registers we'll go to the stack.

How can I edit this to allow adding additional .c files? Right now, I have to do #include "uart.c" to get it to work; which simply embeds said code in main.c rather than having the compiler link it in.

Tried to see if the makefile could first make uart.o from uart.c and then link uart.o and main.o to yield main.hex; not making much progress in this as aspect though.

# OBJECTS ...... The object files created from your source files. This list is
# usually the same as the list of source files with suffix ".o".

It's late, so I wont test it but you could try to add the names of other object to be built to this variable. Eg if your project consists of main.c and uart.c then

OBJECTS = main.o uart.o

You will of-course also have to edit up a uart.h with the things (eg function prototypes, extern declarations of "shared" variables etc) that needs to be seen from both main.c and uart.c and #include that file in both main.c and uart.c .

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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]

You will of-course also have to edit up a uart.h with the things (eg function prototypes, extern declarations of "shared" variables etc) that needs to be seen from both main.c and uart.c and #include that file in both main.c and uart.c .

Thanks Johan! I did try having uart.o in the OBJECT definition but I was getting this strange error:

Personally, when there's a lot of common system headers included in each .c I'd put the #includes in a syshdr.h and then just #include "syshdr.h" in each .c to reduce the "noise". On the occasion that the interrupt header file changes from to I'd then just need to make the change in one place - not edit every .c where it is included.

You might want to rename it to syshdr.inc, perhaps, to stress the fact that it is *not* a *header* (i.e. "interface description of a *.c") as such.

Perhaps. Perhaps not. The use of ".h" as the extension even for nested includes is quite wide-spread.

AFAICR this is the first time I see the notion of making the super-include-files have a filetype of ".inc". Is this a cultural thing, where eg U*ix people do it, and others (eg MS) don't?

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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]

In our coding standard it would most definitely be a .h, we do have the concept of ".i" to but that's for the very specific purpose of a block of externally generated const data that MUST only be #include'd in one .c file - the .i rather than .h makes this clear to the casual reader.

During my C/C++ classes at Uni and even most books I have always seen the use of ".h" and never the use of ".inc".

Doesn't matter what extension you use on a file #include'd in your code -- the preprocessor will process it just the same. That said, personally I think it extremely poor form to use anything other than the .h unless it's something very unusual, like a giant array of PCM audio data which needs to be embedded. Even then, I'd make the embedding of resource files a compile step, and not part of the actual code.

Each to his own, but don't be surprised if you get fired for naming all your C header files "Includes.jpg".

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

You might want to rename it to syshdr.inc, perhaps, to stress the fact that it is *not* a *header* (i.e. "interface description of a *.c") as such.

Perhaps. Perhaps not. The use of ".h" as the extension even for nested includes is quite wide-spread.

AFAICR this is the first time I see the notion of making the super-include-files have a filetype of ".inc". Is this a cultural thing, where eg U*ix people do it, and others (eg MS) don't?

It most definitely isn't a *nix thing. A quick journey through the system headers in a linux install will reveal that many are simply includes of other headers, usually architecture specific. I too have never seen the suggestion to use an extension other than .h for this purpose. Just because a file is used to consolidate common includes, does not make it "not a header".

.inc from my experience is usually reserved for includes in assembly projects.

But as Dean stated, the C compiler does not care what the extension is. #include is simply a text insertion.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

The use of ".h" as the extension even for nested includes is quite wide-spread.

A poor practice, however widespread, is still a poor practice. Replace "sub-optimal" for "poor" in the above if you find it offensive.

glitch wrote:

.inc from my experience is usually reserved for includes in assembly projects.

The choice of extension is arbitrary, but I agree that defacto standards have to be respected. As you might have noticed, I don't have that much of an experience with projects invoving C (I try to avoid them, in fact, being a dedicated C-hater ;-) ). Any other extension would do - fancy .hh?

glitch wrote:

But as Dean stated, the C compiler does not care what the extension is. #include is simply a text insertion.

And that's the problem. The C/*nix folks are not known for being meticulous to the detail, are they. And, if they have chance to take a shortcut, they take it. So it's upon the poor programmer to maintain a discipline, so that the gun won't fire in the direction of the toes.

While it's very easy to implement literal inclusion, it's hard to do it in the proper way. So there's no enforcement of binding the header to the actual source, nor of rejecting irrelevant information from it. There is no syntactical distinction between "include your own header for making sure it matches the body of module", "include a header of the module to be able to link to its functions and variables", and "include an arbitrary text - possibly a collection of headers".

And this is why it is hard to explain to the novices the concept of headers. This thread is in a tutorial section after all, isn't it.

Even \Program Files\Microsoft Visual Studio\VC98\include\windows.h is little more than a bunch of #include's

And, as has already been stated, the technique is used a LOT in the Linux kernel tree.

It may not be "good practice" but it's what C programmers have actually been doing in large projects since time immemorial. In fact that includes me in large in-house projects (one with 57,000 .c files) - some are "meta headers" that just group the inclusion of a bunch of other headers.

Well, that might be a collection, but of what are not headers either. I would assign them a .def :-) OK, this is stretching the things a bit further than you traditionalists would be willing to accept... :-)

clawson wrote:

Even \Program Files\Microsoft Visual Studio\VC98\include\windows.h is little more than a bunch of #include's

Oh, are you trying to tell us that M$ sets the benchmark in good programming practices? :-P

Oh, are you trying to tell us that M$ sets the benchmark in good programming practices?

Well, yes, actually I do believe that. While people decry Microsoft their own source code is very good quality. The reason people call Windows "buggy" is that it does not isolate driver code enough and when Tom, Dick or Harry get a copy of the DDK and write their own webcam or scanner driver it has the ability to crash the kernel (in fact the same is true of anything that is insmod/modprobe'd into the Linux kernel too). The end user's experience is that "Windows has crashed" but more often than not it's 3rd party driver code that has crashed.

In fact a lot of the coding standard we adhere too is based on the writings of Steve Maguire in Writing Solid Code:

He outlines the techniques that Microsoft use internally to avoid the more obvious code faults. If you like it's a bit like a cut-down, less stringent MISRA rule book. That is a very very good book and I highly recommend it to anyone programming in C. While I've had office "purges" over the years and had to discard a lot of books to make room, this remains one of the core books (like K&R, the Borland C reference and Charles Petzold on programming Windows) that I'll retain for all time.

I have never seen anyone who uses a .inc extension for included files in C. In fact, the only variation I have ever really seen other than .h is to use no extension at all (an older practice that has gone out of favor). So I'm not sure how you can say in one breath that you should follow the de facto standard, but in another say to throw the de facto standard out the window only to advocate something else that virtually no one else does.

So I'm not sure how you can say in one breath that you should follow the de facto standard, but in another say to throw the de facto standard out the window only to advocate something else that virtually no one else does.

Well, using an already "assigned" extension for a different purpose would cause confusion; while using an already "unassigned" extension for the non-interface headers would cause at worst a mild attention.

But of course there's no point to push it beyond reason. There are many controversial items in various coding standards to add one more. The thinking programmer develops his own little variations anyway.

I rest the case.

JW

PS. I googled for "file name extension .i" and learned that it is likely to be an INTERCALC file... :-P

There are many controversial items in various coding standards to add one more.

This is not a controversial item, you are just trying to make it into one, pulling arguments out of thin air.

You seriously underestimate the value of established conventions and traditions. The existence of a convention is a value as such, even if the convention is (in your imagination) not optimal. You forgot that there isn't black and white only, but that engineering is a string of compromises and most results are grey. You forgot that it is usually a huge waste of time and money to do things perfect (the 80/20 rule of thumb). Engineering is not about perfection.

You forgot that there isn't black and white only, but that engineering is a string of compromises and most results are grey. You forgot that it is usually a huge waste of time and money to do things perfect (the 80/20 rule of thumb). Engineering is not about perfection.

[wek, standing ashamed in the corner of the room, nodding quietly while concentrating on his yet unshot toes, letting out a sob now and then...]

Well, using an already "assigned" extension for a different purpose would cause confusion;

How is it a different purpose? #include is used to include other files, and that is what is being done. There is nothing in the designation ".h" that implies what the content of the file is other than that it is intended to be included by other files.

There isn't one. But what's the problem? You take the Mfile template. Edit the names of all the C (.c) source files onto the SRC= line, the name of Asm (.S) source files into the ASRC= line and the name of all the C++ (.C) files onto the CPPSRC= line and that's it. Job done.

I have numbers of global variables in my projects. Is it possible to put all the global variables in one .h file and include this file in all the .c file ?

No, this will not work. As I'm sure has been explained earlier in this thread you will get duplicate definitions of those variables, and the linker generating errors.

What you should do has also most likely been described earlier in this thread:
- Place definitions of your global variables in one .c source file.
- Add that .c source file to the project so that it gets compiled.
- Put extern declarations of the ame variables in a .h header file.
- Include that .h header file into all .c source files that needs to see the variables.

Example:

// globals.c
#include "globals.h"
int aGlobalInt;

// globals.h
extern int aGlobalInt;

// userOfGlobals.c
#include "globals.h"
.
.
.
aGlobalInt = 42;
.
.
.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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]

By the way I just looked back at your post and the __floatunsisf error is actually because you are using FP functions without linking with libm.a, nothing to do with your own variables (in the case of that particular error message)

By the way I just looked back at your post and the __floatunsisf error is actually because you are using FP functions without linking with libm.a, nothing to do with your own variables (in the case of that particular error message)

I have numbers of global variables in my projects. Is it possible to put all the global variables in one .h file and include this file in all the .c file ?

Yes, you can have all your "extern" (publically visible) globals listed in one header file. However, you will still need to place them in one of your .c files as well without the "extern" modifier, otherwise you will receive undefined reference errors.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

I am trying to write a header file and put up everything related to TWI in it, leaving only the main processing to the main.c and functions being called as and when required. I want the TWI ISRs to be contained by this header. The program compiles fine, but somehow the ISR just isn't executing. Could you please help me out with this?

An ISR is effectively just a fancy regular function - and anything that results in actual executable code in the binary should be a .c file rather than a .h file. Try creating a TWI.c and TWI.h pair, with the ISRs in the C file.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

The program compiles fine, but somehow the ISR just isn't executing. Could you please advise me something on this?

The snide remark is that you are yet another one that has a problem on line 42 of your source code.

Seriously: We can't say much unless you post your code. It helps boost interest in helping you if you reduce the code to the smallest possible that still builds and executes and displays the problem.

Quote:

And, should I be using a .c file instead of the .h file.

The usual case is a .c file and a .h file. Go read the tutorial here on "Managing large projects".

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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]

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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]

One key thing is if the ISR() calls any functions then either make them static inline - in which case they could actually be located in a .h file - otherwise put them in the same .c file where the ISR() is located so the compiler has some chance of determining register usage and will not be forced to save/restore the entire context.

To add to what Dean says. A typedef does not create any storage. A definition of the array of struct does. The only things you want to avoid in a header file are anything that leads to storage being allocated. So it's the variable definition that needs to be turned into a declaration only. You do this by adding 'extern'.

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.

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.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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.

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?

Think of definition as "implementation". Where a variable is actually allocated, or the body of a function is given.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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:

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.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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.

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.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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?

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.

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 ?

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.

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

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 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.

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.

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.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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 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.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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 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.

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.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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]

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 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.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

"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]

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!

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

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?

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