What does definition mean in the c++ standard's context? Several definitions of the same name are accepted in the different scopes:
int a=1;
int main()
{
int a=1;
}
It is unclear what actually ODR does mean.
What you are referring to here does not come under ODR since the scope of the variable has changed.
A name (other than a statement label) has block scope if it's
declared within a function definition (including that function's
parameter list) or in a brace-enclosed block within that function. Its
scope begins right after its declaration and runs to the end of the
block immediately enclosing that declaration.
You can read the rest of the article here: http://www.drdobbs.com/cpp/scope-regions-in-c/240002006
Related
I'm reading Standard for Programming Language C++ and I cannot find a subclause prohibiting code like follows, which will obviously not compile:
/* Code A */
int main() {
int i;
int i;
}
while this one will compile:
/* Code B */
int main() {
int i;
{ int i; }
}
I've found something related, but I failed to find a matching one:
[basic.def.odr#1]: No translation unit shall contain more than one definition of any variable...
If it's this subclause, I cannot find a subclause explaining why the 2 i's are not the same variable in Code B but are the same variable in Code A;
[basic.scope.block#1]:A name declared in a block ([stmt.block]) is local to that block; it has block scope. Its potential scope begins at its point of declaration ([basic.scope.pdecl]) and ends at the end of its block. A variable declared at block scope is a local variable.
In fact I tried to look for something like or more general than "A name of variable with a block scope cannot be redeclared within its potential scope, excluding nested blocks" like [temp.local#6], but I failed:
[temp.local#6]: The name of a template-parameter shall not be redeclared within its scope (including nested scopes). ...
So can some give me some help? Thanks!
You are looking for [basic.scope.scope]/5
Two declarations potentially conflict if they correspond and cause their shared name to denote different entities ([basic.link]). The program is ill-formed if, in any scope, a name is bound to two declarations that potentially conflict and one precedes the other ([basic.lookup]).
emphasis mine
int i;
void f()
{
int i{};
{
int a = i; // local or global 'i'?
}
}
My question is not which i gets chosen, as it's clear that it's the local one, but rather, where in the standard that is specified.
The closest rule I could find is [basic.lookup.unqual]p6, which says:
In the definition of a function that is a member of namespace N, a name used after the function's declarator-id shall be declared before its use in the block in which it is used or in one of its enclosing blocks ([stmt.block]) or shall be declared before its use in namespace N or, if N is a nested namespace, shall be declared before its use in one of N's enclosing namespaces.
But there it just says that the name has to be declared sometime before the use; it's not what I'm looking for. The example in the same paragraph makes everything clearer as it says what scopes are searched in what order, but it's an example and as such not nominative.
Every other paragraph in [basic.lookup.unqual] doesn't apply to non-member functions. So my question is where in the standard is this specified?
In [basic.scope.declarative] we have:
Every name is introduced in some portion of program text called a declarative region, which is the largest part of the program in which that name is valid, that is, in which that name may be used as an unqualified name to refer to the same entity.
In general, each particular name is valid only within some possibly discontiguous portion of program text called its scope.
To determine the scope of a declaration, it is sometimes convenient to refer to the potential scope of a declaration.
The scope of a declaration is the same as its potential scope unless the potential scope contains another declaration of the same name.
In that case, the potential scope of the declaration in the inner (contained) declarative region is excluded from the scope of the declaration in the outer (containing) declarative region.
[ Example: In
int j = 24;
int main() {
int i = j, j;
j = 42;
}
the identifier j is declared twice as a name (and used twice).
The declarative region of the first j includes the entire example.
The potential scope of the first j begins immediately after that j and extends to the end of the program, but its (actual) scope excludes the text between the , and the }.
The declarative region of the second declaration of j (the j immediately before the semicolon) includes all the text between { and }, but its potential scope excludes the declaration of i.
The scope of the second declaration of j is the same as its potential scope.
— end example ]
(Emphasis mine.)
In your
int a = i;
example, i must refer to the local i because the global i is literally not in scope here.
As it says at the beginning of [basic.lookup.unqual]:
In all the cases listed in [basic.lookup.unqual], the scopes are searched for a declaration in the order listed in each of the respective categories [...]
But it doesn't matter which search order we choose if only one declaration is in scope in the first place.
According to N4567, 3.3.7 paragraph 4 says,
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...
However, I don't see a need for making it clear because such a member definition must be in the scope of that declaration regardless of its lexical positioning. In other words, it seems there is no case where such a member definition dwells outside the scope of the declaration. See the following example:
int always_visible=10;
class some {
int foo(void);
};
int some::foo(void) {
// no ambiguity occurs because its member definition
// is always in the scope of always_visible.
return always_visible;
}
I don't think it's possible for its member definition to precede the declaration of always_visible, in which case the wording above might be useful. Then, why is that clarification needed?
Is the following declaration also a definition?
int f(), i = 1;
If we would rewrite it like this only the second declaration would be a definition:
int f();
int i = 1;
The c++ standard seems to apply the term definition to entire declarations, but to me it seems like it should be applied to parts of declarations.
Each declarator is individually considered to define or merely declare its identifier.
f() is only declared. There should be a definition somewhere else.
i is defined. A subsequent declaration would need to use extern to avoid being a redefinition.
§3.1 Declarations and definitions in the C++14 standard says,
A declaration is a definition unless it declares a function without specifying the function’s body, it contains the extern specifier or…
The paragraph goes on and on with quite a few rules and exceptions. It may perhaps be a defect in the standard that it fails to mention declarators there, despite discussing features that do not immediately appertain to entire declarations.
We also have §8/3,
Each init-declarator in a declaration is analyzed separately as if it was in a declaration by itself.
This could be interpreted to override the "contagious" formulation of rules in §3.1/2.
Both of them are equivalent statements. In both cases, it is declaration for the function f() and declaration + definition for the variable i.
This declaration
int f(), i = 1;
contains two declarations and one definition. That is it declares a function and it declares and at the same time defines an object.
A function definition is a function declaration that includes its body. However in the declaration above the function does not includes its body. So it is only a declaration of function f with unknown number of parameters if it is a C declaration or without parameters if it is a C++ declaration..
As for variable i then this declaration is at the same time a definition of the variable because a memory is reserved for the corresponding object of type int and moreover the reserved memory is initialized by integer constant 1.
From the C Standard (6.7 Declarations)
5 A declaration specifies the interpretation and attributes of a set
of identifiers. A definition of an identifier is a declaration for
that identifier that:
— for an object, causes storage to be reserved for that object;
— for a function, includes the function body
Which determines the scope of a variable, the declaration or definition?
The documentation that I read says that the declaration determines the scope, but my own test said the contrary:
I get "undefined reference to i" error with the linker:
#include <iostream> // Stream declarations
using namespace std;
extern int i; //declaration
int prueba();
int main() {
int i; //Definition
i=6;
prueba();
} ///:~
int prueba(){
cout << i; //cannot access to the scope of i;
}
Declaration. You can declare something external, and it's visible in that file, no matter where it was defined. Similarly, a function is visible anywhere it's declared.
Other than externs and functions though, I can't think of a way to declare a variable that doesn't also define it...
EDIT: OTOH, static (global) variables, the scope is determined by the definition, which is ALSO the declaration.
EDIT 2: Basically I think my point is that you can't really have a definition that isn't ALSO a declaration. so, the only interesting cases are where the declaration isn't also a definition, and that's basically extern with a global in another file, and function declarations...
Both determine the scope - it's just that they determine the scope of subtly different things.
The definition of an object in C/C++ determines at which scope the actual object is visible in and determines the 'largest scope' of visibility for an object or function.
The declaration determines at which scope a particular 'instance' of the name is visible in.
For example, a global variable is defined at global scope (of course) and is potentially visible at global scope or a tighter scope. But the following declaration of the global variable, g_var, is only visible within function foo():
void foo(void)
{
extern int g_var; // the variable g_var has global scope, but this
// declaration has function-level scope
printf( "g_var is: %d\n", g_var);
}
Brian Postow's point that this distinction really only applies to global variables and functions is a a good one to keep in mind.
It enters scope at the ... declarator of the definition. so
int x=3;
{
int x=x; // x is initialized to itself, uninitialized.
}
The iso c++ spec is unfortunately not freely available, so I can't quote chapter and verse.
The definition determines the scope.
From the online version of the C standard:
6.1.2.3 A label name is the only kind of identifier that has function scope.
It can be used (in a goto statement)
anywhere in the function in which it
appears, and is declared implicitly by
its syntactic appearance (followed by
a : and a statement).
6.2.1.4 Every other identifier has scope determined by the placement of
its declaration (in a declarator or
type specifier). If the declarator or
type specifier that declares the
identifier appears outside of any
block or list of parameters, the
identifier has file scope, which
terminates at the end of the
translation unit. If the declarator or
type specifier that declares the
identifier appears inside a block or
within the list of parameter
declarations in a function definition,
the identifier has block scope, which
terminates at the end of the
associated block. If the declarator or
type specifier that declares the
identifier appears within the list of
parameter declarations in a function
prototype (not part of a function
definition), the identifier has
function prototype scope, which
terminates at the end of the function
declarator. If an identifier
designates two different entities in
the same name space, the scopes might
overlap. If so, the scope of one
entity (the inner scope) will be a
strict subset of the scope of the
other entity (the outer scope). Within
the inner scope, the identifier
designates the entity declared in the
inner scope; the entity declared in
the outer scope is hidden (and not
visible) within the inner scope.
Emphasis mine.