Why we cannot use extern to make struct accessible in more than one .c file?
I know that advice is to put a definition of struct in .h file and to include that .h file to every .c file we use that struct, but why we can use `extern for variables but it does not work with structs?
To extern variable:
Define variable in .c file
extern variable in .c file where we want it to be used
build both .c files, the one where variable is defined and the one where it is used
But what is the case with structures?
Correct me if I am wrong somewhere.
The storage-class specifier extern is used to control linkage (see C11 draft 6.2.2), i.e. which identifiers refer to the same object or function.
A struct however, is not a definition (i.e. storage reservation for an object or function body for a function, see 6.7.5), but a type declaration (see 6.2.5.20 and 6.7.2.1.6).
Remark: This distinction is also made explicit in 6.2.2.6:
The following identifiers have no linkage: an identifier declared to
be anything other than an object or a function; ...
Related
From https://www.quora.com/What-are-the-types-of-linkages-in-C-programming
External linkage, means that the variable could be defined somewhere
else outside the file you are working on, which means you can define
it inside any other translation unit rather your current one (you
will have to use the keyword extern when defining it in the other
source code).
Internal linkage, means that the variable must be defined in your
translation unit scope, which means it should either be defined in any
of the included libraries, or in the same file scope.
None linkage, points to the default functions and braces scopes, such
as defining an auto variable inside a function, this will make the
variable only accessable within that function's scope.
Note that:
Any global object is externally linked by default, you can disable that by using the keyword static.
Any constant global object is internally linked by default, you can
disable that by using the keyword extern.
Suppose a global variable is defined in file1 and I want to use it in file2.
In file1, shall the global variable be defined with keyword
extern?
The quote above seem to contradict itself:
"you will have to use the keyword extern when defining it in the other source code" seems to say it should.
"Any global object is externally linked by default" seems to say that it doesn't need to.
In file2, shall I declare global variable with keyword extern?
tldr: You should declare the variable, with extern, in a header file which is included by both file1 and file2. You should then define the variable in file1 only. To define the variable, you declare it without extern (and also without static).
You sound like you have gotten the extern keyword and the standardese term "external linkage" mixed up.
A variable with "external linkage" is accessible from any function in the program, as long as a declaration of the variable is visible to that function. In contrast, a variable with "internal linkage" is accessible from, at most, one "translation unit" (a single source file and all the files it includes), and a variable with "no linkage" is only visible within a single function. (I don't remember off the top of my head whether a static variable declared within a function is considered to have internal linkage or no linkage.)
The extern keyword, applied to a variable declaration, has two effects. First, it guarantees that that variable will be given external linkage, even if the declaration is inside a function (don't do that). Second, and much more importantly, it makes the declaration not be a definition. What that means is, if you have these two files
/* file1.c */
extern int foo;
/* file2.c */
extern int foo;
int main(void) { return foo; }
their combination is not a valid program. You will get an error from the linker, probably reading something like "undefined reference to foo".
To make this a valid program, you must remove the extern from one of the two declarations of foo. That declaration then becomes a definition, and the program will link. (Also, that declaration can then be given an initializer, if you want it to have a value other than 0 at startup.)
If you remove the extern from both of the definitions of foo, the result is, IIRC, implementation-defined. Some C compilers will merge them into a single global variable, and others will issue a link-time error. Sometimes the behavior depends on whether or not the variables have initializers.
It is OK to write
/* file1.c */
extern int foo;
/* file2.c */
extern int foo;
int foo;
This allows you to put the extern declaration in a header file that both .c files include, which reduces the risk of the declarations coming to have inconsistent types (if this happens, the program will exhibit undefined behavior).
c11 draft, 6.2.2, 4th section, states:
For an identifier declared with the storage-class specifier extern in a scope in which a
prior declaration of that identifier is visible,31) if the prior declaration specifies internal or
external linkage, the linkage of the identifier at the later declaration is the same as the
linkage specified at the prior declaration. If no prior declaration is visible, or if the prior
declaration specifies no linkage, then the identifier has external linkage.
i don't think there will be any difference with or without extern keyword. some experiment also indicates that:
following 2 compiled:
extern int a;
extern int a;
int a = 20;
and
extern int a;
int a;
int a = 20;
but not this one:
extern int a;
int a = 10;
int a = 20;
however, i have some impression that once i read about the different behavior when dynamic linkage get involved in windows. I cannot find it though. it would be nice if anyone can confirm.
The text you quoted has a lot of errors. I would recommend not relying on information from that site.
(you will have to use the keyword extern when defining it in the other source code).
Not true, as file-scope definitions have external linkage unless the static keyword is used (or no specifier is used and they are re-declaring something already declared with the static keyword).
It is possible to include a redundant extern in the definition, however there must also be an initializer (otherwise it would be a declaration and not a definition).
Internal linkage, means that the variable must be defined in your translation unit scope, which means it should either be defined in any of the included libraries, or in the same file scope.
Presumably this means "included headers", not "included libraries".
Any constant global object is internally linked by default, you can disable that by using the keyword extern.
This is wrong, "global objects" have external linkage unless declared with static. The author might be mixing up C with C++ (in the latter, const global objects have internal linkage unless otherwise specified).
Suppose a global variable is defined in file1 and I want to use it in file2.
// file1.h (or any other header)
extern object_t obj;
// file1.c
#include "file1.h"
object_t obj; // or: extern object_t obj = { 1, 2, 3 };
// file2.c
#include "file1.h"
This question already has answers here:
How do I use extern to share variables between source files?
(19 answers)
Closed 6 years ago.
Hi I am a C++ developer now I am doing C programming.
My question is which place is better to declare global variable in c program.
Header or source file (provided my global variable is not used in other files)?
I want that variable like private variable in C++.
Assuming your variable is global and non static.
You need to declare it in a header file. We use extern keyword for this. As pointed out in comments, this keywords is not necessary, but most C users prefer to use it in headers, this is a convention.
stackoverflow.h:
#ifndef STACHOVERFLOW_H
#define STACHOVERFLOW_H
extern int my_var;
#ifndef
And you initialize it in source file. (Use of keyword extern is prohibited if you want to provide an initialization value).
stackoverflow.c
#include "stackoverflow.h"
int my_var = 50;
Do not put initialization value in a header, or you will get a linker error if the header is used at least twice.
Now you can use your variable in any other module by including the header.
main.c
#include <stdio.h>
#include "stackoverflow.h"
int main()
{
printf("my_var = %d\n", my_var);
return 0;
}
Including header "stackoverflow.h" in "stackoverflow.c" is a way to get sure definitions in source file match declarations in header file. This permit to have errors as soon as compilation instead of sometimes cryptic linker errors.
Edit: This is not at all the way to make a variable "private". You have to use a static variable to make it "private". See R Sahu's answer
which place is better to declare a global variable in c program
Answer: In source(*.c) file.
Assume the scenario like, I have declared a variable in a header file. I included this header in two different .c files. After the macro expansion step of compilation, these two files will have the global variable with the same name. So it will throw an error like multiple declarations of the variable during the linking time.
Conclusion:-
Keep all global variable declaration on .c file and put it as static if it is doesn't need in other files.
Add extern declaration of the variable in the corresponding header file if it's needed to access from other files
You should not place global non-constant variables anywhere. Global as in declared with extern and available to your whole project. The need to do this always originates from bad program design, period. This is true for C and C++ both.
The exception is const variables, which are perfectly fine to share across multiple files.
In the case you need file scope variables, they should be declared in the .c file and always as static. Don't confuse these for "globals" because they are local to the translation unit where they are declared. More info about how static file scope variables can make sense.
Also note the C standard future language directions:
Declaring an identifier with internal linkage at file scope without
the static storage class specifier is an obsolescent feature.
So if you don't use static your code might not compile in the next version of the C standard.
If you intend to use the global variables in multiple .c files, it is better to declare them in .h files. However, if you want to keep the variables like private member data of classes in C++, it will be better to provide access to the global data through functions.
Instead of
extern int foo;
Use
int getFoo();
void setFoo(int);
That sort of mimics the private access specifiers for member variables of classes.
Generally what you can do is define the variable in a source file, like int g_foo;, then reference this global in other files with extern, like extern int g_foo; do_sth(g_foo);. You could put the extern int g_foo; declaration in a header file, and include that in other source files. It's not recommend to have definitions of data in header files.
If you want it to be global (external linkage), you should put it in .h file. And this is one of the best practise, I think:
public_header.h
#ifdef YOUR_SOURCE
#define EXTERN
#else
#define EXTERN extern
#endif
EXTERN int global_var;
your_source.c
//your source makes definition for global_var
#define YOUR_SOURCE
#include <public_header.h>
other_source.c
#include <public_header.h> //other sources make declaration for global_var
If you want it to be private (internal linkage), the best solution, I think, is just make definition of it right in your source file instead of header file to prevent the header file is included by another source and then make confuse.
your_souce.c
static int private_var;
What is the accepted standard way to define an exposed variable in C? Suppose the setup is the following:
In .h
typedef struct my_struct{
...
} my_struct;
extern my_struct var1;
In .c
my_struct var1;
Is this proper usage or is the compiler doing unnecessary work here? What is the extern actually doing here? My understanding has always been that everything already has an implicit extern by default.
There is a small difference between the implicit extern part when it comes to variables and functions.
If you put
void foo(void);
in a .h file and include the .h file in multiple .cc files, there is no harm since the function is not defined in the .h file. It's only declared.
If you put,
int x;
in the same .h file, then x is defined in every .c file that includes the .h file. You would get similar error for the function if the .h file had:
void foo(void){}
since that is a declaration as well as a definition.
To make a variable such as x to be only a declaration, you need to add the extern keyword.
My understanding has always been that everything already has an implicit extern by default.
This is true, however...
The purpose of explicitly externing var1 in the header is to:
Document your intentions, that var1 is not private.
Notify the compiler that source files that include the header are using a variable declared elsewhere.
Recommendation
Create getter/setter functions and make var1 private (static).
That's exactly right. You need to have the extern in the header in order to tell the compiler that var1 exists and what its type is when it's compiling code that uses it.
(I'm assuming that you are using var1 in more than one .c file, and one of them is defining it. If you're only using it in one .c file then there's no need for the declaration in the header if you define the variable before using it.)
AFAIK, any declaration of a variable or a function in file scope has external linkage by default. static mean "it has internal linkage", extern -- "it maybe defined elsewhere", not "it has external linkage".
If so, why we need extern keyword? In other words, what is difference between int foo; and extern int foo; (file scope)?
The extern keyword is used primarily for variable declarations. When you forward-declare a function, the keyword is optional.
The keyword lets the compiler distinguish a forward declaration of a global variable from a definition of a variable:
extern double xyz; // Declares xyz without defining it
If you keep this declaration by itself and then use xyz in your code, you would trigger an "undefined symbol" error during the linking phase.
double xyz; // Declares and defines xyz
If you keep this declaration in a header file and use it from several C/C++ files, you would trigger a "multiple definitions" error during the linking phase.
The solution is to use extern in the header, and not use extern in exactly one C or C++ file.
As an illustration, compile the following program: (using cc -c program.c , or the equivalent)
extern char bogus[0x12345678] ;
Now remove the "extern" keyword, and compile again:
char bogus[0x12345678] ="1";
Run objdump (or the equivalent) on the two objects.
You will find that without the extern keyword space is actually allocated.
With the extern keyword the whole "bogus" thing is only a reference. You are saying to the compiler: "there must be a char bogus[xxx] somewhere, fix it up!"
Without the extern keyword you say: "I need space for a variable char bogus[xxx], give me that space!"
The confusing thing is that the actual allocation of memory for an object is postponed until link time: the compiler just adds a record to the object, informing the linker that an object should (or should not) be allocated. In all cases, the compiler at leasts will add the name (and size) of the object, so the linker/loader can fix it up.
C99 standard
I am going to repeat what others said but by quoting and interpreting the C99 N1256 draft.
First I confirm your assertion that external linkage is the default for file scope 6.2.2/5 "Linkages of identifiers":
If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.
The confusion point is that extern does not only alter the linkage, but also weather an object declaration is a definition or not. This matters because 6.9/5 "External definitions" says there can only be one external definition:
An external definition is an external declaration that is also a definition of a function (other than an inline definition) or an object. If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than
one.
where "external definition" is defined by the grammar snippet:
translation-unit:
external-declaration
so it means a "file scope" top-level declaration.
Then 6.9.2/2 "External object definitions" says (object means "data of a variable"):
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. If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0.
So:
extern int i;
is not a definition, because it does have a storage-class specifier: extern.
However:
int i;
does not have a storage-class specifier, so it is a tentative definition. And if there are no more external declarations for i, then we can add the initializer equal 0 = 0 implicitly:
int i = 0;
So if we had multiple int i; in different files, the linker should in theory blow up with multiple definitions.
GCC 4.8 does not comply however, and as an extension allows multiple int i; across different files as mentioned at: https://stackoverflow.com/a/3692486/895245 .
This is implemented in ELF with a common symbol, and this extension is so common that it is mentioned in the standard at J.5.11/5 Common extensions > Multiple external definitions:
There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).
Another place where extern has an effect is in block-scope declarations, see: Can local and register variables be declared extern?
If there is an initializer for the object declaration, extern has no effect:
extern int i = 0;
equals
int i = 0;
Both are definitions.
For functions, extern seems to have no effect: Effects of the extern keyword on C functions as there is no analogous concept of tentative definition.
You can only define a variable once.
If multiple files use the same variable then the variable must be redundantly declared in each file. If you do a simple "int foo;" you'll get a duplicate definition error. Use "extern" to avoid a duplicate definition error. Extern is like saying to the compiler "hey, this variable exists but don't create it. it's defined somewhere else".
The build process in C is not "smart". It won't search through all the files to see if a variable exists. You must explicitly say that the variable exists in the current file, but at the same time avoid creating it twice.
Even in the same file, the build process is not very smart. It goes top to bottom and it won't recognize a function name if it is defined below the point of use, so you must declare it higher up.
This question already has answers here:
How do I use extern to share variables between source files?
(19 answers)
Closed 6 years ago.
beginner question about C declaration:
In a .c file, how to use variables defined in another .c file?
In fileA.c:
int myGlobal = 0;
In fileA.h
extern int myGlobal;
In fileB.c:
#include "fileA.h"
myGlobal = 1;
So this is how it works:
the variable lives in fileA.c
fileA.h tells the world that it exists, and what its type is (int)
fileB.c includes fileA.h so that the compiler knows about myGlobal before fileB.c tries to use it.
if the variable is :
int foo;
in the 2nd C file you declare:
extern int foo;
In 99.9% of all cases it is bad program design to share non-constant, global variables between files. There are very few cases when you actually need to do this: they are so rare that I cannot come up with any valid cases. Declarations of hardware registers perhaps.
In most of the cases, you should either use (possibly inlined) setter/getter functions ("public"), static variables at file scope ("private"), or incomplete type implementations ("private") instead.
In those few rare cases when you need to share a variable between files, do like this:
// file.h
extern int my_var;
// file.c
#include "file.h"
int my_var = something;
// main.c
#include "file.h"
use(my_var);
Never put any form of variable definition in a h-file.
Try to avoid globals. If you must use a global, see the other answers.
Pass it as an argument to a function.
Those other variables would have to be declared public (use extern, public is for C++), and you would have to include that .c file. However, I recommend creating appropriate .h files to define all of your variables.
For example, for hello.c, you would have a hello.h, and hello.h would store your variable definitions. Then another .c file, such as world.c would have this piece of code at the top:
#include "hello.h"
That will allow world.c to use variables that are defined in hello.h
It's slightly more complicated than that though. You may use < > to include library files found on your OS's path. As a beginner I would stick all of your files in the same folder and use the " " syntax.
The 2nd file needs to know about the existance of your variable. To do this you declare the variable again but use the keyword extern in front of it. This tells the compiler that the variable is available but declared somewhere else, thus prevent instanciating it (again, which would cause clashes when linking). While you can put the extern declaration in the C file itself it's common style to have an accompanying header (i.e. .h) file for each .c file that provides functions or variables to others which hold the extern declaration. This way you avoid copying the extern declaration, especially if it's used in multiple other files. The same applies for functions, though you don't need the keyword extern for them.
That way you would have at least three files: the source file that declares the variable, it's acompanying header that does the extern declaration and the second source file that #includes the header to gain access to the exported variable (or any other symbol exported in the header). Of course you need all source files (or the appropriate object files) when trying to link something like that, as the linker needs to resolve the symbol which is only possible if it actually exists in the files linked.