What's the difference between int and extern int in C? - c

int i; // A.
extern int i; // B.
I know A is a variable's definition. Namely, the compiler creates an object and assigns a block of memory to the variable i. But what is B? What's the difference between the definition and the declaration?

It's a declaration. It says there is an integer i that will be defined elsewhere.

Case A) is a 'tentative defintion' with external linkage. You can have multiple of these in a single translation unit, and all will refer to the same variable. The definition is called tentative because it will only zero-initialize the variable if there is no other definition with explicit initializer in the translation unit.
Case B) is a declaration but not a definition (tentative or otherwise), because there is no initializer present and no storage will be reserved. There must be a valid definition of the variable elsewhere in this or another translation unit. If there's a previous declaration of the variable with internal linkage in scope, the variable will have internal linkage, otherwise external, ie
static int foo;
extern int foo;
results in a valid tentative definition with internal linkage, whereas
extern int foo;
static int foo;
is invalid as you have a declaration with external linkage followed by a (tentative) definition with internal linkage.
See C99 sections 6.2.2 and 6.9.2 for details.

The extern keyword introduces a variable declaration, not a definition. It says that somewhere in some source file there will be a variable defined with the given declaration, which allows the source file to reference the variable without hassle, but doesn't actually define the variable. This allows one variable defined in one file to be shared and accessed across multiple source files without each file having its own independent copy.

B states that the variable i is defined elsewhere, typically in a different translation unit. The Wikipedia article would not be a bad place to continue your research.

A) As well as declaring the variable i, it is actually implicit definition of i.
B) A declaration of i. You will need the variable i to be defined some where.

Related

Shall an variable with external linkage be defined with keyword external?

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"

Declaration and definition in C programming with extern

This may seem simple to one's eye but, this question is itching me in many ways.
my question is about declaration and defenition on variables in c.
there are actually many explanation in internet regarding this one and there is not just one solution to this issue as many view points are placed in this issue. i want to know the clear existance of this issue.
int a;
just take this is this a declaration or definition?, this one when i use printf, it has 0 as value and address as 2335860. but if this declaration then how come memory is allocated for this.
int a;
int a;
when i do this it says previous declaration of 'a' was here and redeclaration of 'a' with no linkage.
some sources say redeclaration is permitted in c and some say dont what is the truth?
int a; just take this is this a declaration or definition?
int a; if written in global scope is a tentative definition. Which means if no other definitions are available in current compilation unit, treat this as definition or else this is a declaration.
From 6.9.2 External object definitions in C11 specs:
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.
int i4; // tentative definition, external linkage
static int i5; // tentative definition, internal linkage
So you are effectively doing multiple declarations but getting the address and value because of tentative definition rule.
some sources say redeclaration is permitted in c and some say dont
what is the truth?
Redeclaration is permitted in C. But redefinition is not.
Related question: What is the difference between a definition and a declaration?
there are actually many explanation in internet
Prefer a good book instead of internet to get the hold of language. You can choose a good book from:
The Definitive C Book Guide and List
int a is a definition and can be used in place of declaration. A variable can have many declarations but must have only one definition. In case of
int a;
int a;
there are two definition of a in the same scope. Providing linkage to one of them will make your compiler happy
int a;
extern int a;

Why do we need the 'extern' keyword in C if file scope declarations have external linkage by default?

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.

Declaration or Definition in C

From External Variables Wiki:
If neither the extern keyword nor an
initialization value are present, the
statement can be either a declaration
or a definition. It is up to the
compiler to analyse the modules of the
program and decide.
I was not able to fully grasp the meaning of this statement with respect to C. For example, does it imply that:
int i;
is not necessarily a declaration (as I have been assuming until now), but could be a definition as well (by definition of Definition & Declaration on the same webpage, no puns intended)?
In a nutshell, is the above statement:
a. just a declaration, or
b. declaration + definition?
Reference: Variable declaration and definition
Summary of answers received:
Declaration Definition Tentative Definition Initialized
int i; (inside a block) Yes Yes No No
int i=5; (inside a block) Yes Yes No Yes(to 5)
int i; (otherwise) Yes No Yes Yes(to 0)
extern int i; Yes No No No
All definitions are declarations but not vice-versa.
Assuming it's at file scope it's a 'tentative definition'. From 6.9.2/2 "External object definitions":
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.
This means that it would be valid to also have the following in the translation unit:
int i = 42;
since that declaration has an explicit initializer, it's the definition of the variable i.
As far as if the declaration is in a block scope, the standard says the following (6.2.2/2 "Linkages of identifiers"):
Each declaration of an identifier with
no linkage denotes a unique entity.
...
(paragraph 6) The following
identifiers have no linkage: ... a
block scope identifier for an object
declared without the storage-class
specifier extern.
So in block scope, the declaration would be a definition as well.
The C standard says that
A definition of an identifier is a declaration for that identifier that: for an object, causes storage to be reserved for that object (…)
Definitions encompass declarations, i.e., every definition is necessarily a declaration, so it doesn’t make sense to say that
int i;
is not a declaration. It is a declaration which also happens to be a definition. Or, it is a definition, hence a declaration.
In the context of variables:
A declaration of a variable is a statement which describes how this variable looks like. So:
extern int x;
in global scope translates to: "somewhere in the code, there's a variable called x which has type int and extern linkage. A declaration is necessary before you ever refer to x. (The same goes to function declarations.)
A definition is a statement which creates an instance of this variable. So:
int x;
in global scope creates a single variable of type int with extern linkage. So if you'd put that line in a header, every translation unit including that header would try to create its own copy of x, which is undesirable - that's why we only have declarations in header files. The same goes to functions: if you provide the function body, it's a definition.
Also, formally, every definition is a kind of declaration, as it also has to specify how this variable/function looks like - so if a definition already exists in a given scope, you don't need any additional declarations to use it.
From the C99 spec:
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 this is one case in which a simple declaration without an initializer can be a declaration.
As C uses the terms:
A "definition" creates something (which occupies some sort of memory). It also describes something. This means a "definition" is also a "declaration".
A "declaration" just describes something. The idea is that the compiler needs to know how to build the code that uses the thing defined elsewhere. Later, the linker then links the use to the something.
Declarations allow you to compile code and link it (later) as a separate step.

What is the difference between static int a and int a? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Difference between 'global' and 'static global'
What is the difference between statements 1 and 2 :-
#include <stdio.h>
//In the global declaration area
static int a; // 1.
int b; // 2.
Thanks for help.
A static global variable is local to the translation unit it is defined in. So, if you define static int a; in two different translation units, this will create two independent variables. If you define a non-static global variable int b; in two translation units, you will experience a linker error (but you can use extern int b; in one of the two translation units to tell the linker that it should use the global variable from the other translation unit).
Both are variable definitions, however, the static keyword applied to a variable in the "global declaration area" restricts that global variable to be seen only in the translation unit in which it is defined.
They are both in memory for the entire lifetime of the program. The variable that is declared static only has scope in the file in which it is declared where as the variable declared without static can be accessed from other files using an extern declaration.
Original source - http://bytes.com/topic/c/answers/860211-global-variable-static-global-variable
static int a is only accessible within that file. int b can be accessed with extern int b from a different file.
static int a;
int b;
a has internal linkage. b has extern linkage.
C99 6.2.2
6.2.2 Linkages of identifiers
1) An identifier declared in different scopes or in the same scope more than once can be
made to refer to the same object or function by a process called linkage. There are
three kinds of linkage: external, internal, and none.
2) In the set of translation units and libraries that constitutes an entire program, each
declaration of a particular identifier with external linkage denotes the same object or
function. Within one translation unit, each declaration of an identifier with internal
linkage denotes the same object or function. Each declaration of an identifier with no
linkage denotes a unique entity.
3) If the declaration of a file scope identifier for an object or a function contains the storage-
class specifier static, the identifier has internal linkage.
A static variable's life extends across the lifetime of the program. However, scope rules still apply.
If you define your static variable outside of a method (normally at the beginning of the class) your variable will be available from anywhere within that class.
You can't change the value of these objects. They're normally used for storing things like API keys.

Resources