Why use function prototypes? - c

Why use function prototypes in C? It seems sort of redundant because we already declare the function name, argument types, and return type in the definition. Do the prototypes have to be declared before the function is defined or used for the optimizations?

Generally speaking, you don't need to explicitly declare functions because defining them also declares them. Here are two situations where you would need to:
The definition of the function is in an external module.
For example, if the function is defined in definer.c, but you want to call it from user.c, you will need to declare the function in user.c or a file included by it (typically, definer.h).
The definition of the function comes after a call to it.
For example, if you have two functions that call each other, you will need to declare the second one before the definition of the first one.

With the declaration of a function the compiler can check the consistent use of parameters and return value, and can compile the code even if the function is not implemented in this module.
If the function is only declared but not implemented in the respective module, this gap will be closed by the linker, not the compiler.
It's similar to declaring extern variables. If you'd define them, the memory for them would be allocated multiple times. That's why you should never define variables in h-files, but declare them there. Including the h-file would result in multiple allocations of memory.

While a function definition specifies what a function does, a function prototype can be thought of as specifying its interface.
Creating library interfaces:
By placing function prototypes in a header file, one can specify an interface for a library.

Related

Practical Applications or Value of Function Prototype Scope

First off: When searching for answers, I am allowed to [tag] the areas to search. This posting interface should support that too.
Besides error checking which only requires types, not identifiers, what are some of the practical applications one might encounter for leveraging function prototype scope? What are some of the advantages to this?
function(int index, float array[index]);
//function prototype with names
vs
function(int, float);
//function prototype(without identifiers)...
The definition of a function always includes the return argumen, function name and function arguments including the type and names It seem that having a prototype scope would be redundant since the arguments are re-declared anyways with names:
Prototype:
return_type return_name(argument_type, ...);
Function Declaration:
return_type return_name(argument_type argument_name, ...){
compound_statement_function_block;
}
The only value I can see is that it reserves the function name within the file scope namespace meaning the function name could be used within the prototype:
int func(int func); //Proto type declaration. Compiler allows this
//but throws warning about func() redeclaration
//but nothing about the arguments.
int function(int function){
int function;
}
I had originally thought that the scope was independent of names meaning file_scope_variable_name was different than file_scope_function_name. They are contextually and significantly different enough to be such and I thought that is what the standard called for however the compiler I am using, gcc, won't allow it. It will however allow main re-declared as a tag in the struct/union name space at any scope since they a block element like a function:
int func(int func){
typedef struct {
int func;
}; //Cannot use func as a variable name at function scope
//since it is an argument even though
//this is within a different namespace
typedef union func{
int (*func)(int func); //Shows func() name and arg. names
//are different namespaces.
union u{
int func;
//...
}
} ;
}
int main(int main){
typedef struct main {
int main;
};
}
It seems 'main' is a reserved keyword at the file level for variable names and function names but not struct/tag union names. It accepts this at the file level:
struct main {
int main;
//...
} not_main;
It makes no sense why the namespaces are as such for the prototype. If it didn't have some practical utility, it wouldn't be a distinction.
Preliminary
You are mixing several distinct concepts that apply to C identifiers: scope, namespace, and linkage:
Scope is the region of program text where a given association between an identifier and a particular program entity is visible and can be used.
Namespace describes the fact that C allows the same identifier to be used in the same scope to identify objects in certain contextually distinguishable categories: labels, tags, structure and union members, and everything else.
Linkage is about whether a variables or function declared in one translation unit can be accessed from others (external linkage), or only from elsewhere in the same translation unit (internal linkage), or only within the scope of its definition (no linkage).
Scope and linkage are substantially separate considerations. File scope declarations of ordinary identifiers can have either external or internal linkage. Block scope declarations of ordinary identifiers can have either external linkage or no linkage. All declarations of identifiers in other namespace have no linkage.
The question
... is a bit wide-ranging, but I'll try to hit on the main points.
Besides error checking which only requires types, not identifiers,
what are some of the practical applications one might encounter for
leveraging function prototype scope? What are some of the advantages
to this?
Having a function prototype scope makes it possible to include parameter names in function prototypes. If the prototype did not provide a scope for the function parameter identifiers, then the only scope to which they could belong would be file scope, and that would imply that every parameter name would have to be distinct from every other in the file, and from that of every file-scope variable. It would also imply that function parameters could be accessed from outside the function. And of course there would be an issue with multiple declarations of a function that provide different parameter names. What a mess!
It is true that you don't need prototypes that are not part of function definitions to provide parameter names -- that is optional, after all. But allowing it is a great convenience for everyone. Among the benefits are
it makes it easier to create separate prototypes (just take the one from the function definition and remove the function body)
it makes function prototypes far more meaningful to human readers, especially with good choices of parameter names
it allows compilers to provide more useful diagnostic messages
The definition of a function always includes the return argumen,
function name and function arguments including the type and names It
seem that having a prototype scope would be redundant since the
arguments are re-declared anyways with names
You seem to be looking at it backward. One of the effects of function prototype scope is that giving parameter names in a prototype isn't redundant. Except for prototypes that are part of a function definition, the scope of the identifier declarations in a function prototype is the prototype. They don't have to match from one prototype of a given function to another (though typically they do). The only parameter names that matter to the function body are the ones associated with the function's definition.
But for the reasons given earlier, among others, we generally want parameter names to appear in function prototypes. Especially so in prototypes appearing in headers or otherwise used in translation units different from the one containing the function definition.
The only value I can see is that it reserves the function name within
the file scope namespace meaning the function name could be used
within the prototype
It does have that effect, though I rarely see a function's identifier used as the name of one of its own parameters. But it's a bit more common that a file-scope function name appears also as the name of some other function's parameter. Or that a file-scope variable name appears as the name of a function parameter.
I had originally thought that the scope was independent of names
meaning file_scope_variable_name was different than
file_scope_function_name.
No, that would be a question of namespace. Function and variable names belong to the same namespace (that of ordinary identifiers), which is appropriate because they are not always distinguishable from each other by context.
[my compiler] will however allow main re-declared as a tag in the struct/union name space at any scope since they a block element like a function
Yes, main can be used as a tag, despite also being the identifier of a function with external linkage. And also as a label and as a member of arbitrarily many structures and unions. This is because those are separate name spaces. Rather than trying to learn a rule for how namespaces are established, it is probably best to just remember the different namespaces -- other than those of all the structures and unions, which can be taken as a category, there are only three.
Also, main can be used as a parameter name in a function prototype or as a local variable of a function, because such identifiers have different scope.
And main can be used as the name of a separate (file-scope) function in as many different translation units as you like, so long as no TU has more than one, and provided that exactly one in the whole program has external linkage.

Must a function prototype be declared everywhere the function has to be used?

Is it necessary to declare a prototype for a function everywhere a function is called.
All functions are extern by default and hence why arent they treated as extern variables, where 1 extern declaration of a variable and 1 local definition is sufficient to be accessed among all files?
Yes, we need to declare the prototype of function before using the function.
I recommend to write the prototypes in a header file, if you are using many extern functions.
Include the header file in the source file to use those function.

Is it safe to declare function prototypes for functions that do not exist?

I am writing a C program that uses some macros that make function prototypes in batches, however I often don't write all of the functions the macro makes prototypes for. This compiles fine in gcc, but I'm wondering if this is unsafe in any way or if it will cause errors if I use a different compiler?
The prototypes only declare the name and use (parameters, types) of functions. If the compiler encounters a use of such a function, it will check your use against the prototype and warn if your use is not compatible.
When the development environment starts linking the objects, it will search for functions used but not found in the object. Linking fails if a function that is used is not found.
Since the prototype only declares the function and its usage, it does not require the function to be present IF the function is not used. Hence it is safe to declare prototypes for functions that you don't provide.
(But it could be confusing for another programmer who will expect the function to exists if he/she sees the prototype.)

How does C limit a static function's use to only its file?

I understand that a static function in C allows that particular function to only be call within the confines of that file. What I am interested in is how this occurs. Is it being placed into a specific part of memory or is the compiler applying a specific operation to that function. Can this same process be applied to a function call in assembly?
Declaring a function static doesn't really prevent it from being called from other translation units.
What static does is it prevents the function from being referred (linked) from other translation units by name. That will eliminate the possibility of direct calls to that function, i.e calls "by name". To achieve that, the compiler simply excludes the function name from the table of external names exported from the translation unit. Other than that, there's absolutely nothing special about static functions.
You still can call that function from other translation units by other means. For example, if you somehow obtained a pointer to static function in other translation unit, you can call it through that pointer.
It doesn't make it into the object's name table which prevents it from being linked into other stuff.
Functions and other names are exported as symbols in the object file. The linker uses these symbols to resolve all sorts of dangling references at link time (e.g. a call to a function defined in another file). When you declare it static, simply it won't be exported as a symbol. Therefore it won't be picked up by any other file. You could still call it from another file if you had a function pointer to it.
It's in fact the opposite. When a function is not static, its name is written somewhere in the object file, which the linker can then use to link other object files using this function, to the address of that function.
When the function is declared static, the compiler simply doesn't put the name there.

function prototypes in main or before main in C

Should the function prototype in C be in main or before main. I was taught before main, but my friends class book shows it in main. Which is the correct way?
His book shows it:
int main()
{
void numberTable();
numberTable();
}
void numberTable()
{
int num;
...rest of the code...
}
Both are correct.
If you add the function declaration inside main, its scope is inside the main { }.
If you add it outside main, its scope is the entire source file.
It can be both way. But If you declare outside main, then you can access everywhere in the code, in other case,its scope is within main.
The reason to define the function before main is to avoid the function declaration that would be necessary if you define the function after main. It is common for C modules to be coded in this style, that is: functions defined in dependency order, in order to avoid the need for declarations of functions that are local in scope (we should be careful how we use the word scope here - scope is not enforced by the C linker).
Both are correct; however, it's not a good style in reality.
A common good practice: put all those functions declaration and definition in other headers and source files: header.h + header.c
Either way can be made to work. Declarations outside main() (or, more generally, outside any function) typically leads to less repetition.
When you declare the function inside main(), that declaration only applies in main(). If some other function (e.g. function_1()) also calls the relevant function (e.g. numberTable()) and appears before the other function is defined, then you have to declare numberTable() inside function_1() as well (violating DRY: Don't Repeat Yourself, and also SPOT: Single Point of Truth). If, on the other hand, the declaration of numberTable() was outside any function and before any function in the file, then all functions can use the one declaration.
If you have multiple source files involved, then the rules become simpler. All functions callable from other files should be declared in a header (header.h). That header should be included in every file that references any of the functions declared in header, and also in each of the files that defines each of the functions that is declared in the header. The header should be included outside of any function in the files where it is used. (The C standard requires this for the standard headers.) This ensures that all the code has a consistent view of declaration of each function. Eventually, you will get to big enough programs that there may even be multiple headers. The same basic rules apply - declare functions in headers; include the headers (outside of any function) where the functions are used and defined. (See also What are extern variables in C.)

Resources