This question already has answers here:
Using extern keyword to call functions
(4 answers)
Effects of the extern keyword on C functions
(10 answers)
Should functions be made "extern" in header files?
(5 answers)
Is extern keyword for function necessary at all in C?
(4 answers)
Closed 5 years ago.
Is there any difference between declaring a function (bar) this way:
char *foo(char *pch)
{
extern char *bar(); /* this line here */
...
}
Or this way?
char *foo(char *pch)
{
char *bar(); /* this line here */
...
}
The 2011 C Standard says in 6.2.2/5:
If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern.
So there is no technical difference.
But as already noted in the comments, both are considered bad style. A function declaration does not belong inside another function where it will be used. If you use that pattern and want to change the declaration of the function, you would need to find and modify all the places it's used! A function with external linkage should be declared in a header file. A function with internal linkage (using the static keyword) should be declared somewhere near the beginning of a source file.
Related
This question already has answers here:
Alternative (K&R) C syntax for function declaration versus prototypes
(5 answers)
Closed 3 years ago.
I stumbled upon these lines when looking into putchar.c
I'm wondering about why the arguments ptr and c are declared outside the arguments body ?
Is this some kind of "good old way" or does it have some actual use ?
int
_putchar_r (ptr, c)
struct _reent *ptr;
int c;
{
return __sputc (c, _stdout_r (ptr));
}
Indeed it is the "olden" way of declaring a function's parameters.
I kind of like it, because it serves as a constant reminder that all a function's parameters are local variables that exist only in the scope of the function and that any argument passed into any function ALWAYS is a value copy.
Its a K&R C style introduced in classic C Programming Book
It is a function definition with an identifier list. Each identifier in the identifier list is declared before the compound statement of the function.
So a function can be defined either with a parameter type list or using the old style with an identifier list.
This question already has answers here:
Why does initializing an extern variable inside a function give an error?
(5 answers)
Closed 6 years ago.
extern int a = 10; // it is not giving error
int main ()
{
extern int b = 10; //it is giving error
return 0;
}
error: ‘b’ has both ‘extern’ and initializer
extern int b = 10;
Referring to C11 (N1570) 6.7.9/5 Initialization:
If the declaration of an identifier has block scope, and the
identifier has external or internal linkage, the declaration shall
have no initializer for the identifier.
The rule is placed within constraints section, so any conforming compiler should reject the code, that violates it.
The point of extern keyword at the block scope is to declare some existing object from outside scope. It would not make much sense to declare an object and give it some other value at the point of declaration.
The recommended way of declaring external objects is to put their declarations at the file scope (at the top of source code), thus they are easy to spot and manage by maintenance programmer.
This question already has answers here:
Tentative definitions in C and linking
(3 answers)
Closed 6 years ago.
#include<stdio.h>
int check,check;
void main(){
printf("Hello!!");
}
When I compile this piece of code, everything goes on normal but when I give this inside the main function,
#include<stdio.h>
void main(){
int check,check;
printf("Hello!!");
}
I get an error like
C:\MinGW\bin>cc ex1.c
ex1.c: In function 'main':
ex1.c:4:11: error: redeclaration of 'check' with no linkage
int check,check;
^
ex1.c:4:5: note: previous declaration of 'check' was here
int check,check;
^
Why is it so?
This is possible in global scope, because that is considered an tentative definition.
Quoting C11, chapter §6.9.2
A declaration of an identifier for an object that has file scope without an initializer, and
without a storage-class specifier or with the storage-class specifier static, constitutes a
tentative definition.
However, in the block scope (function scope), there's no tentative definition, hence the code tries to create two identifiers with the same name which is cause for the re-declaration error, because they actually denote the same object.
You can read more about it here.
That said, since C99, for hosted enviroments, void main() is not a valid signature anymore, it has to be int main(void) at least.
This question already has answers here:
Effects of the extern keyword on C functions
(10 answers)
Closed 7 years ago.
I was wondering if there is any difference if skip extern storage class specifier while declaring a function? Specifically, is there any difference between following two?
void foo ();
and
extern void foo();
is there any difference between following two?
Basically, no.
Each function declaration, is extern by default, (i.e., in absence of any specific storage-class specifier).
Quoting C11, chapter §6.2.2, Linkages of identifiers
If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern.
This question already has answers here:
About Tentative definition
(2 answers)
Closed 9 years ago.
As we know extern declaration of variables can be initialized.
#include<stdio.h>
extern int a=5; //will work as both definition and declaration.
int main()
{
}
Why this programme is compiling and running with no error.
extern int a=5; //will work as both definition and declaration.
int main()
{
}
int a; // isn't it second definition??
C has a concept of a "tentative definition". Most definitions without initializers are "tentative", so an arbitrary number of them are allowed, as long as they don't conflict with each other. At the end of the translation unit, the definition of the variable becomes basically the composite of those (e.g., if one definition says the variable is const and another says it's volatile, the variable will end up as both const and volatile.
A definition with an initializer is never tentative, so only one of them is allowed.