Why compiler doesn't generate redeclaration variable i error?
Od C Standards#6.2.1p4 Scopes of identifiers
Każdy inny identyfikator został zakres określony przez umieszczenie deklaracji (w deklaratorze lub specyfikatorze typu). Jeśli deklarator lub specyfikator typu deklarujący identyfikator pojawia się poza jakimkolwiek blokiem lub listą parametrów, identyfikator ma zasięg pliku, który kończy się na końcu jednostki tłumaczeniowej. Jeśli deklarator lub specyfikator typu, który deklaruje identyfikator pojawia się wewnątrz bloku lub na liście deklaracji parametrów w definicji funkcji, identyfikator ma zasięg bloku, który kończy się na końcu skojarzonego bloku. Jeśli deklarator lub specyfikator typu deklarujący identyfikator pojawia się na liście deklaracji parametrów w prototypie funkcji (nie jest częścią definicji funkcji), identyfikator ma zakres prototypu funkcji, który kończy się na końcu deklaratora funkcji. Jeśli identyfikator oznacza dwie różne jednostki w tej samej przestrzeni nazw, zakresy mogą zachodzić na siebie. Jeśli tak, zakres jednego podmiotu (zakres wewnętrzny) zakończy się ściśle przed zakresem innego podmiotu (zakres zewnętrzny). W zakresie wewnętrznym identyfikator oznacza jednostkę zadeklarowaną w zakresie wewnętrznym; jednostka zadeklarowana w zewnętrznym zakresie jest ukryta (i niewidoczna) w zakresie wewnętrznym.
Od C standards#6.8.5p5 Iteration statements
oświadczenie iteracja jest blok, którego zakres jest ściśle podzbiorem zakresu jej otaczającego bloku. Ciało pętli jest także blokiem, którego zakres jest ściśle określonym podzestawem zakresu instrukcji iteracji.
Więc w ten kod:
for (int i = 0; i == 0; i++)
{
printf("%d\n", i);
long int i = 1; // Why doesn't redeclaration error?
printf("%ld\n", i);
}
zakres identyfikator z nazwą i
jest nakładanie i ta nazwa przestrzeni, i
zadeklarowane w for (int i = 0; i == 0; i++)
ma zewnętrzną zakresu i zgłoszonemu wewnątrz pętli body long int i = 1;
ma wewnętrzny zakres.
wewnątrz ciała pętli, po tym stwierdzeniem
long int i = 1;
w i
zadeklarowanym w zakresie zewnętrznej jest niewidoczny i printf()
drukowania wartość i
widzialnym zakresem wewnętrznej, która jest 1
.
To zachowanie jest również znane jako Zmienne cienie, które występuje, gdy zmienna zadeklarowana w pewnym zakresie ma taką samą nazwę jak zmienna zadeklarowana w zewnętrznym zasięgu.
Język C umożliwia zmianę cieniowania i dlatego kompilator nie generuje żadnego błędu dla tego. Jednak w kompilatorze gcc
, jeśli użyjesz opcji -Wshadow
, otrzymasz komunikat ostrzegawczy - declaration shadows a local variable
.
Czy nie otrzymujesz również ostrzeżenia, że 'int main' nie zwraca wartości? – MFisherKDX
@MFisherKDX Cppreference mówi: "Ciało funkcji głównej nie musi zawierać instrukcji return: jeśli sterowanie osiągnie koniec głównego bez napotkania instrukcji return, efektem jest wykonanie return 0;" – rsp
Zgodnie z 5.1.2.2.3 z n1570 (szkic C11): "dojście do} kończącego główną funkcję zwraca wartość 0" (o ile typ powrotu jest zgodny z 'int'.) – lockcmpxchg8b