View previous topic :: View next topic |
Author |
Message |
kgng97ccs
Joined: 02 Apr 2022 Posts: 97
|
Function definitions and prototypes |
Posted: Mon Jul 18, 2022 12:35 am |
|
|
I would like to understand the best practices regarding function definitions and function prototypes.
1. I understand that if I have a function defined before the main() function, there is no need to have a function prototype before the function definition. However, is it a good practice to always place a function prototype before the corresponding function definition, and if yes, why?
Code: | …
/* Function prototype, explicitly placed here, or in a .h file that is included here */
void f_test1(unsigned int8 PWM_pin);
/* Function definition, explicitly placed here, or in a .c file that is included here */
void f1_test1(unsigned int8 PWM_pin)
{
…
}
void main()
{
…
}
|
2. When defining an ISR for an interrupt, is it a good practice to have a function prototype for the ISR?
Incidentally, I have, by chance, noticed that when an #int_xxx line and the associated ISR are placed after the main() function and there is no ISR function prototype listed before the main() function, the compiler seems to compile without error, and the .lst file shows the #int_xxx and ISR after the main() function. In comparison, the compiler will give an error if a regular function (non-ISR) is placed after the main() function and there is no corresponding function prototype before the main function.
3. If I have a .c file containing the definition of several functions, but not all of the functions are used by the main() function, what would be the recommended way of managing function prototypes and the .c file? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Mon Jul 18, 2022 2:39 am |
|
|
A function definition is automatically it's own prototype.
Where separate prototypes are required, is if using multiple compilation units.
They are then essential, otherwise the units that don't actually contain the
definitions, will not know the format of the functions.
For compilation without MCU's, just loading the definitions in front of where
they are used, covers everything.
On the ISR's, the key here is 'where they are used'. Unlike all normal
functions, that are called from somewhere else in the code, ISR's are
'called' by the header saying #INT_xxx. So they don't actually care or
require a definition in front of the main.
Functions are not actually included in the compilation, till they are used.
This is why it is perfectly acceptable to load 'libraries' that contain many
function definitions that are not used by the code.
So if you are not using MCU's, then simply have your definitions as include
files loaded before you use them. |
|
|
kgng97ccs
Joined: 02 Apr 2022 Posts: 97
|
|
Posted: Thu Jul 21, 2022 8:59 pm |
|
|
Thank you, Ttelmah.
1. If I have a user-defined function that calls one or more other user-defined functions, I understand (if I am not wrong) that the function definitions for functions that are called should be included (using #include) before the function definition of the calling function.
However, if I use function prototypes (in any order) before the function definitions, will that eliminate the need to place the function definitions in any particular order?
2. If I have a long main() function but wish to organize the code into smaller units each performing a particular task, so that the main() function does not look crowded, I understand that one way is to use a function for each task.
However, if each of these functions uses many variables defined in the main() function, I would have to pass many variables to the function. I have seen programs that void this by defining these variables as global variables. Would this be a good approach?
I will appreciate any ideas on how best to manage this situation. Thank you. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Thu Jul 21, 2022 10:16 pm |
|
|
You'd have to have the prototypes in exactly the same order as the
definitions need to be. There has to be a prototype or a definition
before any function is used.
Globals are generally a bad thing. They cost memory, and increase the
probability of variables being corrupted.
Quote: |
By using a local variable you decrease the dependencies between your
components, i.e. you decrease the complexity of your code. You should only
use global variable when you really need to share data, but each variable
should always be visible in the smallest scope possible.
|
Learn about passing variables using pointers, or by reference,
Use globals only for things that are 'global'. Don't use them habitually. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1348
|
|
Posted: Fri Jul 22, 2022 12:29 pm |
|
|
If all of the prototypes are before all of the function definitions, then the prototypes do *not* need to be in any specific order. All that matters is any prototypes referenced by a function definition occur before that function definition.
EX:
Code: |
void f1();
void f2();
void f2(){
f1();
}
void f1(){
/// stuff
}
|
is perfectly valid even though f1 and f2 are in a different order.
However the following isn't legal:
Code: |
void f2();
void f2(){
f1();
}
void f1();
void f1(){
/// stuff
}
|
Since the definition of f2() hasn't seen the prototype of f1() yet. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Sun Jul 24, 2022 3:43 am |
|
|
As I said.
Quote: |
in front of where they are used
|
|
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1348
|
|
Posted: Sun Jul 24, 2022 10:06 am |
|
|
Ttelmah wrote: | As I said.
Quote: |
in front of where they are used
|
|
it was more a clarification of your other statement:
Ttelmah wrote: |
You'd have to have the prototypes in exactly the same order as the
definitions need to be.
|
|
|
|
kgng97ccs
Joined: 02 Apr 2022 Posts: 97
|
|
Posted: Fri Sep 09, 2022 1:22 am |
|
|
Just wanted to say thank you, Ttelmah and Jeremiah, for your help.
I have now memorized these important points:
Quote: | There has to be a prototype or a definition before any function is used. -- Ttelmah |
Quote: | If all of the prototypes are before all of the function definitions, then the prototypes do *not* need to be in any specific order. All that matters is any prototypes referenced by a function definition occur before that function definition. -- Jeremiah |
It is nice to know that the function prototypes do not need to be in any specific order. The examples make these concepts clearer.
Thanks again. |
|
|
|