For C++ this is covered in the draft C++ standard section 3.3.2
Point of declaration:
The point of declaration for a name is immediately after its complete
declarator (Clause 8) and before its initializer (if any), except as
noted below. [ Example:
int x = 12;
{ int x = x; }
Here the second x is initialized with its own (indeterminate) value.
—end example ]
and:
[ Note: a name from an outer scope remains visible up to the point of
declaration of the name that hides it.[ Example:
const int i = 2;
{ int i[i]; }
declares a block-scope array of two integers. —end example ] —end note
]
So in your case:
int x[x];
The const int x
is visible until the closing ]
. To refer to const int x
after that point you can use a qualified identifer:
::x
Of course this begs the question, why not just use different names and not have to deal with these edge cases?
C
The equivalent quotes form the draft C99 standard would be from section 6.2.1
Scopes of identifiers (emphasis mine):
Structure, union, and enumeration tags have scope that begins just
after the appearance of the tag in a type specifier that declares the
tag. Each enumeration constant has scope that begins just after the
appearance of its defining enumerator in an enumerator list. Any
other identifier has scope that begins just after the completion of
its declarator.
and:
[...] 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.
there is no way to make the x
in the outer scope visible in C.