How can I write variable definition without declaration? - c++

I can write declaration or declaration with definition. Examples:
int x = 1; // declaration and definition
extern int x; // only declaration
bool f(); // only declaration
bool g() {} // declaration and definition
class X; // declaration
class X {}; // declaration and definition
So we can see that this is possible to write only declaration and declaration with definition.
But how I can write only definition? I heard that this is possible.

There is no definition without a declaration, since the meaning of the first term includes the second. Further, I provided some information from the C++ drafts (6.2. Declarations and definitions):
A declaration is said to be a definition of each entity that it
defines.
Link: https://eel.is/c++draft/basic.def

You cannot write a definition for something that is undeclared, point blank. But you do have C++ constructs for writing definitions that may not serve as a first declaration. Here they are:
struct C {
static int i;
};
int C::i = 1;
namespace N {
extern int i;
}
int N::i = 2;
Neither int C::i = 1; nor int N::i = 2; may serve as an initial declaration for i. Those definitions are invalid unless a previous declaration of each respective i is present. So in a way they are non-declaring definitions.
This answer may be contentious, and possibly not fall under the answers you had in mind, but those would be the examples.

The variable declaration means, specifying the type and name of the variable.
Example: int A means the type of variable (memory location in memory) is int, and the name is A.
But in variable definition, memory is allocated for the variable, and value is assigned.

Related

Initializer overrides extern [duplicate]

I am very very sorry. I didn't know my incomplete code attachment would create such a mess. I am very glad to see so many sincere helps.
This code will compile:
int myadd(int, int);
static int main_stat = 5;
int main()
{
int i, j;
main_stat = 13;
j = myadd(-1,7);
i = main_stat;
cout << j << i; // 3 and 13
return 0;
}
myadd.cpp
extern int main_stat = -3;
int myadd(int x,int y)
{
int t = main_stat;
t = x + y;
y = t +main_stat;
return y; // will return 3
}
See I defined and extern linking main_stat. Why is that legal? I thought you could only link and not define.
Is storage allocated in the stack frame of myadd function call? Global static are allocated on heap, I believe, right?
EDIT
I am sorry, but I think this time I will narrow down my questions:
From C++ Primer 4ed
An extern declaration may include an initializer (when combined
becomes definition) only if it appears outside a function.
I am clear about one-definition rule.
Q1. Which copy of main_stat does myadd(int,int) uses when it is called? The same copy as the main has, but with a different value (which I can test) ? Or does each function has its own static global copy?
Q2. Is memory allocated on the heap for these global static variables? I know many things are up to implementation, but isn't heap used for static variables?
Q3. I know the followings two are valid
extern int x; // means int x is defined elsewhere
extern int x = 3; // declared and defined
Why do we want the second one if we can just declare a static global variable within the namespace of myadd ? How does it make things clear like aschepler said?
All variable declarations with an initializer are also definitions;
that's an overriding rule. Regardless of extern. There are even
cases where you need an extern on a definition: you can only
instantiate a template using a variable which has external linkage. And
const variables have internal linkage by default, so you need
something like:
extern int const i = 42;
if you want to use it to instantiate a template<int const*>.
The following is a declaration and definition:
int x;
Adding extern says "make it a declaration only, please".
But when you are providing a value, the line has to be a definition, so the variable gets extern storage class and you just happen to be defining it right in place anyway:
extern int x = 3;
The linkage semantics are as they usually are for extern, and the storage location is just as it would be for a normal definition int x = 3 — i.e. in that TU at namespace scope. myadd is not relevant at all.
It's a hard one to "prove", because it's a case of "there's no rule against it".
Here's the best quote:
[n3290: 3.1/2]: A declaration is a definition unless it declares
a function without specifying the function’s body (8.4), it
contains the extern specifier (7.1.1) or a linkage-specification25 (7.5) and neither an initializer nor a
function-body, [..]
And some other pertinent information:
[n3290: 3.5/2]: A name is said to have linkage when it might denote the same object, reference, function, type, template, namespace or value as a name introduced by a declaration in another scope:
When a name has external linkage, the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.
When a name has internal linkage, the entity it denotes can be referred to by names from other scopes in the same translation unit.
When a name has no linkage, the entity it denotes cannot be referred to by names from other scopes.
[n3290: 3.5/12]:The name of a function declared in block scope and the name of a variable declared by a block scope extern declaration
have linkage. If there is a visible declaration of an entity with
linkage having the same name and type, ignoring entities declared
outside the innermost enclosing namespace scope, the block scope
declaration declares that same entity and receives the linkage of the
previous declaration. If there is more than one such matching entity,
the program is ill-formed. Otherwise, if no matching entity is found,
the block scope entity receives external linkage. [..]
extern int main_stat=-3;
declares and defines main_stat, While:
extern int main_stat;
just declares the variable main_stat.
You can have as many declarations as you want but you can have only one Definition.
The keyword extern, indicates External Linkage. Without it main_stat would be static and have Internal linkage and you cannot not use main_stat from another translation unit.
Is storage allocated in the stack frame of myadd ?
No definitely not on the stackframe of add.
Where the memory is allocated is implementation defined but you have the assurance that the object will be alive throughout the duration of the program.
The question apparently stems from some misconception.
Some people believe that extern keyword always turns a definition into a non-defining declaration. This is simply not true.
The keyword extern simply gives the declared entity external linkage. It can be applied to declarations. It can be applied to definitions (and remember that definitions are declarations as well).
So, saying that one can't define an extern entity is absolutely incorrect. One can. There's no problem with that at all.
The confusion is usually caused by the fact that when you apply extern to a definition like
int x; // no initializer
that definition suddenly turns into a non-defining declaration. This is true, but this is is no more than a one-off quirk of extern keyword that has to be remembered. If you take a definition like
int x = 42;
then applying the extern keyword to it will still preserve it as a definition, i.e. no quirks in this case.
First, according to your comment, the file containing the main function has the definition static int main_stat = 10;. You should be aware that this is not the same variable as you defined in the file containing myadd because as static variable its scope is restricted to that file. Indeed, thanks to that static variable with the same name, main is not able to access the variable you defined in this file.
But that doesn't mean that either variable was created on the stack. Both are separate global variables, it's just that the variable main_stat in the file containing main (I'll call that file main file for short, and this one myadd file) is not available in any other file, while the variable main_stat you defined here can be accessed from any file which contains the declaration extern main_stat; (note: without initializer!). The main file cannot contain this declaration, however, because it would conflict with the static variable of the same name.
Note that giving an initializer makes your declaration of the variable a definition, that is, it's the same as if you had omitted the extern (note however that if a variable is declared constant, the extern may not be omitted because constants are by default static). The only global extern declarations which are not also definitions are those with extern, but without initializer.
Everyone else has covered this pretty well, but just to show the variants in one place:
int x; // #1
is a declaration and definition. The initial value of x is zero.
int x = 3; // #2
is a declaration and definition.
const int cx; // #3
is illegal in C++.
const int cx = 3; // #4
is a declaration and definition, but cx has internal linkage if this is its first declaration in the translation unit.
extern int x; // #5
is a declaration but NOT a definition. There must be a definition of x somewhere else in the program.
extern int x = 3; // #6
is a declaration and a definition. The extern is unnecessary, but makes things clear.
extern const int cx; // #7
is a declaration but NOT a definition. There must be a definition of cx somewhere else in the program.
extern const int cx = 3; // #8
is a declaration and a definition. The extern is needed unless the previous declaration above was already seen.

What does the spec mean by the highlighted sentence in §3.3.7/1 item 5?

§3.3.7/1 item 5:
The potential scope of a declaration that extends to or past the end
of a class definition also extends to the regions defined by its
member definitions, even if the members are defined lexically outside
the class (this includes static data member definitions, nested class
definitions, and member function definitions, including the member
function body and any portion of the declarator part of such
definitions which follows the declarator-id, including a
parameter-declaration-clause and any default arguments (8.3.6)).
Would it be possible to identify such a declaration in the first example given in this paragraph?
typedef int c;
enum { i = 1 };
class X {
char v[i];
int f() { return sizeof(c); }
char c;
enum { i = 2 };
};
It looks as though it's saying, among other things, and in addition to the answer above, that given all the code outside that class definition, even if X::f were defined outside the class, like so:
typedef int c;
enum { i = 1 };
class X {
char v[i];
int f();
char c;
enum { i = 2 };
};
int X::f() {
return sizeof(c);
}
that, in the context of the definition of X::f, c would refer to the member variable X::c, not the typedef above, because even though it kind of looks like it's being defined globally, f actually lives in X's scope.
Yes. The declaration of the member c of the class X is visible inside the definition of f, even though lexically, it comes afterwards. This means that the sizeof expression applies to the member, and not to the type outside, which mean it will return 1, not whatever the size of int is (probably 4).
Also, the enum constant X::i should, according to this rule, be visible when the array v is declared, although this surprises me, and I would strongly suggest to avoid such code - sounds like a compiler bug or developer misunderstanding just waiting to happen.
Edit: Lightning Strikes in Orbit is probably right that the comment about parts of the declarator only applies to out-of-line definitions.

Declaring two global variables of same name in C

I have declared two global variables of same name in C.
It should give error as we cannot declare same name variables in same storage class.
I have checked it in C++ — it gives a compile time error, but not in C. Why?
Following is the code:
int a;
int a = 25;
int main()
{
return 0;
}
Check it out at : Code Written at Ideone
I think this probably is the reason
Declaration and Definition in C
But this is not the case in C++. I think in C++, whether the variable is declared at global scope or auto scope the declaration and definition is happening at the same time.
Could anyone throw some more light on it.
Now when I define the variable two times giving it value two times it gives me error
(instead of one declaration and one definition).
Code at : Two definitions now
int a;
int a;
int a;
int a = 25;
int main()
{
return 0;
}
In C, multiple global variables are "merged" into one. So you have indeed just one global variable, declared multiple times. This goes back to a time when extern wasn't needed (or possibly didn't exist - not quite sure) in C.
In other words, this is valid in C for historical reasons so that we can still compile code written before there was a ANSI standard for C.
Although, to allow the code to be used in C++, I would suggest avoiding it.
This is what the classic text "The C Programming Language" by Dennis Ritchie and Brain Kernighan says:
An external declaration for an object is a definition if it has an initializer.
An external object declaration that does not have an initializer, and does not contain the extern specifier, is a tentative definition.
If a definition for an object appears in a translation unit, any tentative definitions are treated merely as redundant declarations.
If no definition for the object appears in the translation unit, all its tentative definitions become a single definition with initializer 0.
So for example:
extern int a =123; // this declaration is a definition as a is initialized to 123
int a; //this is a tentative definition
int a;
int a;
int a;
/*all the above the three tentative declarations are redundant*/
int a;
int a;
int a;
Futher in the code if no where do something as a=100 where we consider a corresponding to this global scope variable and not any other local variable with the same name and type, then ultimately, the global variable a shall be initialized to 0

Under what circumstances can an extern variable be used in definition?

I am very very sorry. I didn't know my incomplete code attachment would create such a mess. I am very glad to see so many sincere helps.
This code will compile:
int myadd(int, int);
static int main_stat = 5;
int main()
{
int i, j;
main_stat = 13;
j = myadd(-1,7);
i = main_stat;
cout << j << i; // 3 and 13
return 0;
}
myadd.cpp
extern int main_stat = -3;
int myadd(int x,int y)
{
int t = main_stat;
t = x + y;
y = t +main_stat;
return y; // will return 3
}
See I defined and extern linking main_stat. Why is that legal? I thought you could only link and not define.
Is storage allocated in the stack frame of myadd function call? Global static are allocated on heap, I believe, right?
EDIT
I am sorry, but I think this time I will narrow down my questions:
From C++ Primer 4ed
An extern declaration may include an initializer (when combined
becomes definition) only if it appears outside a function.
I am clear about one-definition rule.
Q1. Which copy of main_stat does myadd(int,int) uses when it is called? The same copy as the main has, but with a different value (which I can test) ? Or does each function has its own static global copy?
Q2. Is memory allocated on the heap for these global static variables? I know many things are up to implementation, but isn't heap used for static variables?
Q3. I know the followings two are valid
extern int x; // means int x is defined elsewhere
extern int x = 3; // declared and defined
Why do we want the second one if we can just declare a static global variable within the namespace of myadd ? How does it make things clear like aschepler said?
All variable declarations with an initializer are also definitions;
that's an overriding rule. Regardless of extern. There are even
cases where you need an extern on a definition: you can only
instantiate a template using a variable which has external linkage. And
const variables have internal linkage by default, so you need
something like:
extern int const i = 42;
if you want to use it to instantiate a template<int const*>.
The following is a declaration and definition:
int x;
Adding extern says "make it a declaration only, please".
But when you are providing a value, the line has to be a definition, so the variable gets extern storage class and you just happen to be defining it right in place anyway:
extern int x = 3;
The linkage semantics are as they usually are for extern, and the storage location is just as it would be for a normal definition int x = 3 — i.e. in that TU at namespace scope. myadd is not relevant at all.
It's a hard one to "prove", because it's a case of "there's no rule against it".
Here's the best quote:
[n3290: 3.1/2]: A declaration is a definition unless it declares
a function without specifying the function’s body (8.4), it
contains the extern specifier (7.1.1) or a linkage-specification25 (7.5) and neither an initializer nor a
function-body, [..]
And some other pertinent information:
[n3290: 3.5/2]: A name is said to have linkage when it might denote the same object, reference, function, type, template, namespace or value as a name introduced by a declaration in another scope:
When a name has external linkage, the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.
When a name has internal linkage, the entity it denotes can be referred to by names from other scopes in the same translation unit.
When a name has no linkage, the entity it denotes cannot be referred to by names from other scopes.
[n3290: 3.5/12]:The name of a function declared in block scope and the name of a variable declared by a block scope extern declaration
have linkage. If there is a visible declaration of an entity with
linkage having the same name and type, ignoring entities declared
outside the innermost enclosing namespace scope, the block scope
declaration declares that same entity and receives the linkage of the
previous declaration. If there is more than one such matching entity,
the program is ill-formed. Otherwise, if no matching entity is found,
the block scope entity receives external linkage. [..]
extern int main_stat=-3;
declares and defines main_stat, While:
extern int main_stat;
just declares the variable main_stat.
You can have as many declarations as you want but you can have only one Definition.
The keyword extern, indicates External Linkage. Without it main_stat would be static and have Internal linkage and you cannot not use main_stat from another translation unit.
Is storage allocated in the stack frame of myadd ?
No definitely not on the stackframe of add.
Where the memory is allocated is implementation defined but you have the assurance that the object will be alive throughout the duration of the program.
The question apparently stems from some misconception.
Some people believe that extern keyword always turns a definition into a non-defining declaration. This is simply not true.
The keyword extern simply gives the declared entity external linkage. It can be applied to declarations. It can be applied to definitions (and remember that definitions are declarations as well).
So, saying that one can't define an extern entity is absolutely incorrect. One can. There's no problem with that at all.
The confusion is usually caused by the fact that when you apply extern to a definition like
int x; // no initializer
that definition suddenly turns into a non-defining declaration. This is true, but this is is no more than a one-off quirk of extern keyword that has to be remembered. If you take a definition like
int x = 42;
then applying the extern keyword to it will still preserve it as a definition, i.e. no quirks in this case.
First, according to your comment, the file containing the main function has the definition static int main_stat = 10;. You should be aware that this is not the same variable as you defined in the file containing myadd because as static variable its scope is restricted to that file. Indeed, thanks to that static variable with the same name, main is not able to access the variable you defined in this file.
But that doesn't mean that either variable was created on the stack. Both are separate global variables, it's just that the variable main_stat in the file containing main (I'll call that file main file for short, and this one myadd file) is not available in any other file, while the variable main_stat you defined here can be accessed from any file which contains the declaration extern main_stat; (note: without initializer!). The main file cannot contain this declaration, however, because it would conflict with the static variable of the same name.
Note that giving an initializer makes your declaration of the variable a definition, that is, it's the same as if you had omitted the extern (note however that if a variable is declared constant, the extern may not be omitted because constants are by default static). The only global extern declarations which are not also definitions are those with extern, but without initializer.
Everyone else has covered this pretty well, but just to show the variants in one place:
int x; // #1
is a declaration and definition. The initial value of x is zero.
int x = 3; // #2
is a declaration and definition.
const int cx; // #3
is illegal in C++.
const int cx = 3; // #4
is a declaration and definition, but cx has internal linkage if this is its first declaration in the translation unit.
extern int x; // #5
is a declaration but NOT a definition. There must be a definition of x somewhere else in the program.
extern int x = 3; // #6
is a declaration and a definition. The extern is unnecessary, but makes things clear.
extern const int cx; // #7
is a declaration but NOT a definition. There must be a definition of cx somewhere else in the program.
extern const int cx = 3; // #8
is a declaration and a definition. The extern is needed unless the previous declaration above was already seen.

Is "int a;" a declaration or definition in C and in C++?

Is int a; a declaration or definition in C? Is there any difference in C++?
I was always thinking it's just a declaration, until today...
Is it a declaration or a definition?
A declaration describes an object, whereas a definition requests the creation of an object. All definitions are also declarations, but the reverse is not true.
In the case of int a;, what it is depends on where it is placed in the source code:
Within a function, int a; is a definition - it requests the creation of an int variable with automatic storage duration (and of course also a declaration);
At file scope, the answer is different in C and C++. In C, int a; is a tentative definition (of which there can be more than one, as long as the types and linkage are agreeable); in C++, it is an ordinary definition with external linkage.
Within a struct or union specifier, int a; is a declaration of a member.
Where does it appear in your program?
In most contexts, it is both a declaration and definition.
OTOH, extern int a; is a declaration only.
Consider:
int a;
It's a definition as well as a declaration.
Consider the following example...
int i;
printf("%d", i);
Some junk value will be printed. Which obviously means it's got a memory location.
If you want to just declare a variable and not define it then go for "extern" keyword.
Thus extern int b; is just a declaration and not a definition.
Example:
extern int var;
int main(void)
{
var = 10;
return 0;
}
Thus the above program will throw an error as "var" was not defined anywhere.