MISRA Discussion Forums

Full Version: Rule 8.1 and static functions
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Rule 8.1 states, "Functions shall have prototype declarations and the prototype shall be visible at both the function definition and call."

My question concerns a subset situation of this rule: why should functions marked static have prototype declarations visible at the function definition?

Here is an example of the scenario, all in the same .c file:

static int8_t my_function( void );

...

float64_t my_other_function( void )
{
...
my_int8_var = my_function();
...
}


static int8_t my_function( void )
{
...
}


Elsewhere in the file there my be other calls of my_function too. This file conforms to rule 8.1. If I re-arrange the textual order of the file to make sure that the definition of my_function occurs before any calls of it, then the prototype effectively becomes redundant:

static int8_t my_function( void );


static int8_t my_function( void )
{
...
}

...

float64_t my_other_function( void )
{
...
my_int8_var = my_function();
...
}



Realistically, the prototype for my_function, usually placed towards the top of the .c file, is done by copy and paste from the function definition, with a semicolon added to the end of it. To me, as long as the textual order is right, the prototype just becomes something with no value to maintain, e.g. if you were to alter the function signature you would have to do so in two places rather than just one.

I have tried to work out why MISRA would want the rule as it is, inclusive of static functions. (I'm ok with the rule otherwise.) I reckon that it might be for this reason: the prototype for static functions are there for the day when someone does some maintenance on the .c file and adds a call to a static function textually before the definition of the function. With a prototype there, the call would be checked for consistency; without a prototype there, if the maintainer forgets to alter the textual order of the function definitions, the function call is unchecked and so has a risk of being in error.

Have I answered my own question?
Quote:the prototype for static functions are there for the day when someone does some maintenance on the .c file and adds a call to a static function textually before the definition of the function
Quote:Have I answered my own question?
I think you have :-)
In my view, code has a tendency to stay around a lot longer than the original developer. If you take these defensive measures now, the future should be less problematical!

Hope this helps.

Bill Forbes.
As the previous posts have both noted, the main purpose for this rule in respect of static functions is that it aids maintenance. It can also act as a helpful "Table of Contents" for the file's functions.
if you use a function that is neither prototyped nor implemented you should get a requirement-warning from the checker tooling.
having at least either of it makes sure that the usage is checkable for correctness using the checker tooling. doing so is not critical.
adding both for static functions is for my perception merely a redundancy and thus deserves only a advisory-level warning.
According to my copy of K&R (half-way down section A7.3.2), "There are two styes in which functions may be declared. In the new style, the types of parameters are explicit and are part of the type of the function; such a declaration is also called a function prototype."

Now, a function definition is a declaration followed by compound-statement, so ISTM that while a definition like
Code:
static void foo() {...}
is a function with no prototype, the alternative definition
Code:
static void foo(void) {...}
is a function *with* a prototype. For calls to this function, made later in the same translation unit, the prototype is visible at the function call. If anyone adds a call above the function definition, that would be a violation and your checker tool and/or compiler should complain at you.

You can have multiple declarations for an object, so
static void foo(void);
...
static void foo(void) {...}
is legal. If the function was not static, and calls to the function are made from other translation units, then obviously the extra prototype is needed and has to be in the header file that is common to both the file defining the function and the file using it. Again, if the header is absent, I get a warning which I fix. For static functions, defining every static function as
Code:
static void foo(void);
static void foo(void)
{
  ...
}
seems a bit pointless. But if that's necessary to make Lint general enough to check the other case (where the prototype is in a header file) then I don't mind doing it.