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