Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
obnoxs
PostPosted: Feb 26, 2011 - 04:40 AM
Rookie


Joined: Sep 09, 2009
Posts: 21
Location: Australia

Sorry if this was already asked.
Not explicitly said this tutorial seems to indicate that say "usart.h" does not need to include "usart.c" is that true?
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Feb 26, 2011 - 12:27 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62366
Location: (using avr-gcc in) Finchingfield, Essex, England

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.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Feb 26, 2011 - 06:53 PM
10k+ Postman


Joined: Mar 27, 2002
Posts: 18598
Location: Lund, Sweden

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.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
prabu
PostPosted: Mar 18, 2011 - 01:20 PM
Hangaround


Joined: Feb 22, 2007
Posts: 107


Dear 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
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Mar 18, 2011 - 02:51 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62366
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

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:
Code:
//foo.h - declaration of a variable and function
extern int n;
long my_function(int number, char c);

Code:
//foo.c - definition of a variable and function
int n;
long my_function(int number, char c) {
 return c * number;
}

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
prabu
PostPosted: Mar 21, 2011 - 09:36 AM
Hangaround


Joined: Feb 22, 2007
Posts: 107


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;
}

Thanks,
Prabu
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Mar 21, 2011 - 09:41 AM
10k+ Postman


Joined: Mar 27, 2002
Posts: 18598
Location: Lund, Sweden

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.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
clawson
PostPosted: Mar 21, 2011 - 12:22 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62366
Location: (using avr-gcc in) Finchingfield, Essex, England

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:

Is storage allocated?

yes) it's a definition
no) it's a declaration

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Mar 21, 2011 - 01:15 PM
10k+ Postman


Joined: Mar 27, 2002
Posts: 18598
Location: Lund, Sweden

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.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
clawson
PostPosted: Mar 21, 2011 - 01:37 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62366
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

A Definition is inherently a declaration.

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.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
gastro54
PostPosted: Jun 06, 2011 - 05:32 PM
Rookie


Joined: Nov 27, 2009
Posts: 47


Awesome 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.
 
 View user's profile Send private message  
Reply with quote Back to top
Mickjc75
PostPosted: Jul 22, 2011 - 06:32 AM
Rookie


Joined: Mar 16, 2006
Posts: 20


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.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
JohanEkdahl
PostPosted: Jul 22, 2011 - 08:28 AM
10k+ Postman


Joined: Mar 27, 2002
Posts: 18598
Location: Lund, Sweden

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.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
hobbss
PostPosted: Jul 28, 2011 - 02:52 PM
Hangaround


Joined: Oct 06, 2010
Posts: 475
Location: Chicago

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:

Code:

#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
Code:

FILE com0_str = FDEV_SETUP_STREAM(usart0_putchar, usart0_getchar, _FDEV_SETUP_RW);


Functions then call like:
Code:

fprintf(comExt, "blah blah blah\n");


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.,
Code:

uint8_t myPrintFxn(const char* _fmt, uint8_t portNum){}
uint8_t myPrintFxn_P(const char* _fmt, uint8_t portNum){}


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?
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Jul 28, 2011 - 02:54 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62366
Location: (using avr-gcc in) Finchingfield, Essex, England

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?

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
hobbss
PostPosted: Jul 28, 2011 - 03:04 PM
Hangaround


Joined: Oct 06, 2010
Posts: 475
Location: Chicago

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.
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Jul 28, 2011 - 03:08 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62366
Location: (using avr-gcc in) Finchingfield, Essex, England

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?

Here's an example:
Code:
// first.c
#include <stdio.h>
#include <avr/io.h>

void foo(void);

int uart_putchar(char c, FILE *stream)
{
   // blah blah
   UDR = c;
   return 0;
}

FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);

int main(void) {
   fprintf(&uart_str, "Hello");
   foo();
   while(1);


Code:
// second.c
#include <stdio.h>

extern FILE uart_str;

void foo(void) {
     fprintf(&uart_str, "Hi from foo");
}

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
hobbss
PostPosted: Jul 28, 2011 - 03:19 PM
Hangaround


Joined: Oct 06, 2010
Posts: 475
Location: Chicago

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.
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Jul 28, 2011 - 03:27 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62366
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

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 ?

That is:
Code:
// uart.c
#include <stdio.h>
#include <avr/io.h>
#include "uart.h"

FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);

int uart_putchar(char c, FILE *stream)
{
   // blah blah
   UDR = c;
   return 0;
}

Code:
// uart.h
extern FILE uart_str;

int uart_putchar(char c, FILE *stream);
Code:
// main.c
#include <stdio.h>
#include "uart.h"

void foo(void);

int main(void) {
   fprintf(&uart_str, "Hello");
   foo();
   while(1);
}

Code:
// second.c
#include <stdio.h>
#include "uart.h"

void foo(void) {
     fprintf(&uart_str, "Hi from foo");
}

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
hobbss
PostPosted: Jul 28, 2011 - 03:51 PM
Hangaround


Joined: Oct 06, 2010
Posts: 475
Location: Chicago

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.
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits