extern declaration and function definition both in the same file - c

I was just browsing through gcc source files. In gcc.c, I found something like
extern int main (int, char **);
int
main (int argc, char **argv)
{
Now my doubt is extern is to tell the compiler that the particular function is not in this file but will be found somewhere else in the project. But here, definition of main is immediately after the extern declaration. What purpose is the extern declaration serving then?
It seems like, in this specific example, extern seems to be behaving like export that we use in assembly, wherin we export a particular symbol outside of the module
Any ideas?

You are misunderstanding the extern - it does not tell the compiler the definition is in another file, it simply declares that it exists without defining it. It's perfectly okay for it to be defined in the same file.
C has the concept of declaration (declaring that something exists without defining it) and definition (actually bringing it into existence). You can declare something as often as you want but can only define it once.
Because functions have external linkage by default, the extern keyword is irrelevant in this case.

Functions are implicitly extern in C. Including extern is just a visual reminder. Side note, to make a function not extern you can use the static keyword.

In a function declaration, extern simply declares that the function has external linkage, which is the default; the extern keyword is utterly useless in this context, and the effect is identical to a normal declaration/prototype without the extern keyword.

The warnings likely suggested a function prototype was missing. That's all.

The definition of the main function:
int main(int argc, char **argv) { ... }
is already a declaration is the prototyped syntax of the function main with external linkage. This means a prototyped declaration with extern just before the main definition is redundant.

Related

Is the visibility of a function written in C across the project files by default?

I have heard that functions in are called "extern" by default. So, according to this the scope of functions should be inside, entire the project, isn't it? I believe haven't seen this. I just like to know that is it really visible across the project files by default?
The article link: https://www.geeksforgeeks.org/understanding-extern-keyword-in-c/
It says:
" First, Let’s consider the use of extern in functions. It turns out that when a function is declared or defined, the extern keyword is implicitly assumed. When we write.
int foo(int arg1, char arg2);
The compiler treats it as: extern int foo(int arg1, char arg2);
Since the extern keyword extends the function’s visibility to the whole program, the function can be used (called) anywhere in any of the files of the whole program, provided those files contain a declaration of the function. (With the declaration of the function in place, the compiler knows the definition of the function exists somewhere else and it goes ahead and compiles the file). So that’s all about extern and functions. "
You can find this in section "6.2.2 Linkages of identifiers" of the C11 standard draft N1570.
It says:
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.
The use of the extern modifier is optional for function definitions. However, many C developers use it as a matter of style, to indicate to somebody reading the source that there's no point looking for the definition of the function in the same file.
Yes all functions (if there is no other modifier) are implicitly extern. You may alter it with static modifier, which makes the function visible only for the file it is written in. Another quite common use is extern inline which makes inline functions visible for another files, not just the module they are defined in.
Yes, C defaults to global visibility for new named objects in filescope unless they're declared static.
Note that extern does not mean global visibility. It means previously declared visiblity OR (if there was no such previous declaration) global visibility.
extern optional on non-static functions (with some special meanings for the new (C>=C11) inline functions) but for filescope variable declarations it is sometimes needed to differentiate between a declaration and a tentative definition.
Examples:
void globalFunc(void);
void globalFunc(void){ }
static void fileLocalFunc(void);
void fileLocalFunc(void){ } //ok, file-local because the previous declaration was file-local
static void another_fileLocalFunc(void);
extern void another_fileLocalFunc(void){ } //extern is optional for functions
static int fileLocal_variable;
extern int fileLocal_variable; //ok, file-local, because the previous declaration was file-local
//some noncompiling stuff:
#if 0 || CONFLICTING_FUNC_DECLARATIONS0
extern void conflictingFuncDeclarations0(void);
static void conflictingFuncDeclarations0(void);
#endif
#if 0 || CONFLICTING_FUNC_DECLARATIONS1
void conflictingFuncDeclarations1(void);
static void conflictingFuncDeclarations1(void);
#endif
#if 0 || CONFLICTING_VAR_DECLARATIONS0
int conflictingVarDeclarations0;
static int conflictingVarDeclarations0;
#endif
If you're on a POSIX system, you can compile a translation unit into an object (*.o) file and then use the nm utility on it to see which names it exports (or attempts to import).

Declaration and definition confusion in C

This answer confused me.
If we have two lines in same .c file:
extern int c;
int c;
How is the first line of code a declaration and second a definition?
Aren't both declarations?
How these two lines differ?
The extern keyword is what makes the first line a declaration. It say "this variable exists somewhere". A line like that can appear in a header file.
The second line is a definition because the extern keyword is not present. If you were to have this line in a header file, two source files that include that header will both define that variable and linking those two files will result in a variable redefinition error.
When the program you're writing consists of multiple source files linked together, where some of the variables defined, for example, in source file file1.c need to be referenced in other source files, so this is the reason why using extern.
About your question how these lines differ:
extern int c;
int c;
A variable is defined when the compiler allocates the storage for the
variable while
A variable is declared when the compiler is informed that a variable
exists (and this is its type); it does not allocate the storage for
the variable at that point.
so only int c; is defined while extern int c; is declared .
A definition creates space for a variable:
int c;
Wherever you put this line, either local, global, this says that a new variable c of type int shall come to life.
extern int c;
A declaration says that there is somewhere else some variable c of type int. By using extern, you say that c is defined somewhere else. If you put only an extern declaration without a definition somewhere else, you will have a link error. Using extern is the equivalent of a forward declaration of a function:
/* declaration */
int f(int x);
vs.
/* definition */
int f(int x) {
return x*x;
}
The first means that there is somewhere a function f returning an int and accepting an int as parameter. The latter is the actual function, its code, which also works both as a declaration and a definition.
IMO, this declaration-vs-definition naming is confusing. I hardly remember which one is what, and I usually need to think about it. You should, however, understand the what extern means and what a forward declaration is.
Long story short, defining something means providing all of the necessary information to create that thing in its entirety. However, declaring something means providing only enough information for the computer to know it exists.
Edit: To be clearer: A definition both defines and declares, a declaration ONLY declares. When you are using the extern keyword by definition you are not defining anything. Your confusion stems from the understanding of extern.

extern on function prototypes?

my_math.h
// case 1
unsigned int add_two_numbers(unsigned char a, unsigned char b);
//case 2
extern unsigned int add_two_numbers(unsigned char a, unsigned char b);
What is the difference between case 1 and case 2? I never used extern for function prototypes but looking at someone's code (who is way more experienced than I am) I see extern always used when declaring the function prototype. Can anyone point please point the difference? (or point me to a link where I can find specific information). Google says that is something related to the external linkage. Can anyone point me to an example where one would work and the other wouldn't?
I am using embedded C (KEIL), if it makes any difference.
extern is a linkage specifier for global linkage. Its counterpart is static, which specifies file-local linkage. Since global linkage is the default in C, adding extern to the declaration makes no difference for the declaration of a function. For a variable it prevents automatic memory allocation and using it is the only way to just declare a variable at global scope.
If you just google the keyword, you will find many articles e.g. this one:
geeks for geeks
I learned the following for variables years ago from an experienced programmer:
glo.h:
#ifndef EXTERN
#define EXTERN extern
#endif
...
EXTERN int gMyVar;
...
main.c:
#define EXTERN
#include "glo.h"
"glo.h" anywhere inlcuded will just declare all global variables. "glo.h" included in main.c will allocate the storage for the variables. I believe this method was common practice.
For a (non-inline) function, it doesn't make any difference, extern is implicit if no storage-class specifier is given (note, that this applies only to functions, objects are different), so it's only a matter of style what you use.
I've seen both (never use extern for functions/only use it for the declarations in the header), maybe some use extern for symmetry with object identifiers, or to make it easier to grep for external symbols.
Choose whatever you prefer and stay consistent, it doesn't make a difference.

extern with global definition of variable in c

I have the following source code which interests me.
#include <stdio.h>
extern int foo;
int foo = 32;
int main()
{
printf("%d", foo);
}
This a perfectly normal piece of code, and when I compile it with
gcc -Wall -Wextra -pedantic foo.c
I get no warnings.
And it seems weird, because a variable is defined both as external, and also global in the same file.
I'm quite sure that it's easy to the linker to find the reference for the external variable in the same file, but doesn't it look like a coding error? And if so, why doesn't the compiler warn about this?
There's nothing weird. You first made a declaration of a variable (you promised the compiler that it exist) and then you actually defined it. There's no problem in that.
Also, by default, all variables that aren't local to functions and aren't defined as static are extern.
You seem to misunderstand what extern does. extern simply makes your declaration just a declaration instead of a definition.
int i; //definition of i
extern int i; //declaration of i
It is perfectly normal to have multiple declarations of the same variable, but only one definition should be present in the whole program. Compare this with a function
void f(void); //declaration
void f(void) //definition(and redeclaration)
{
} //definition
In order to use a variable or function, you only need its declaration. Its definition may appear anywhere in the program (the linker will find it). Anywhere can be the same file, another file, or even an external library.
And it's seems weired, because a variable is defined both as external, and also global in the same file.
extern int foo;
says: it declares without defining an object of type int named foo.
int foo = 32;
it declares and defines an object of type int named foo with external linkage.
There is no contradiction and it is valid C code.
The difference is that the former is a declaration -> extern declares a variable and says it will be available somewhere around. You can have as many declarations as you want and the latter is a definition which must be there exactly once.
So there should be no warning and no error.
extern is a way to provide visibility to a variable that is defined elsewhere...
extern is like a promise...
in example.h
extern int g;// promises that this will be in the object code to anything that includes example.h
example. c
int g;

Terminology: Forward Declaration versus Function Prototype

To me these terms are essentially synonymous when using the C programming language. In practice I might prefer "forward declaration" for in-file prototypes versus "function prototype" for prototypes included via a header file. But even that is an artificial distinction when you consider what happens after preprocessing. Perhaps I'm missing something.
Is there a consensus for when to use one term versus the other?
The term "prototype" refers to a specific declaration syntax; specifically, that the number and types of parameters to the function appear in the declaration. Given a function definition of
int foo(int a, char *b) {...}
you can have any of the following declarations:
int foo(); // a declaration, but not a prototype
int foo(a, b); // a declaration, but not a prototype
int foo(int, char *); // a declaration and a prototype
int foo(int a, char *b); // a declaration and a prototype
IMO those are not really synonyms.
To me "function prototype" refer to the function name and its parameters' and return's types. It does not only apply to what you call "forward declaration". All functions have a prototype.
We more often make a difference between a function declaration and its corresponding definition.
I use the term forward declaration for the following kind of struct declaration with a definition.
struct Foo;
A function declaration need not be a full prototype, for compatibility with pre-1989 (K&R) C.
char *foo(); // NOT the same as char *foo(void)
The only concept in C I'm aware of is the distinction between declaration and definition. A prototype is a declaration and can happen anywhere, anytime and the definition which is the actual implementation od the given object. by that concept, there is no thing called forward declaration, ther's only an order of declaration.
I don't know if there is a consensus, but I think the cleanest way to do it would be:
Place all declarations in header files, never in source or .c files. (I think you mean declaration when you say forward declaration.)
Place all definitions in source files
I don't like to place declarations in files because you can have conflicting declarations without errors in C, which can cause segfaults, for example: if a.c has
int foo(char *str_one, char *str_two, char *str_three);
and b.c has
int foo(char *str_one, char *str_two);
you will not get warnings nor errors, and calls made to foo() from b.c will not place all the parameters on the stack where they should be, meaning foo() will just grab something from the stack and treat it as str_three, possibly leading to a segfault. So for me, declarations go to header files and definitions go to source files.

Resources