2013-04-19 7 views
9

W końcu wyśledziłem błąd literówki, który jest podobny do następującego kodu. Ale czy kompilator nie powinien tego wykryć (domyślnie opcje)?Dlaczego kompilator pozwala inicjować zmienną samą w sobie?

#include <stdio.h> 

int main() 
{ 
    int c = c; 
    return printf("%d\n", c); 
} 


$ gcc --version   
gcc (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3 
+10

Przywołujesz niezdefiniowane zachowanie przy inicjalizacji; kompilator nie musi diagnozować problemu ani definiować, co robi, gdy go napotka. –

+8

Założę się, że mój lewy but, kiedy włączasz ostrzeżenia (-Wall w GCC), ostrzega cię, kiedy to robisz. Staraj się nie ignorować ostrzeżeń ;-) – nothrow

+0

vc został wykryty. – BLUEPIXY

Odpowiedz

7

Nie rozumiem, dlaczego nie skompilowałoby się. Definicja dzieje się przed inicjalizacją. Oczywiście ta inicjalizacja jest bezcelowa, jednak nie ma powodu, aby nie działała z punktu widzenia kompilatorów.

C nie ma tego samego rodzaju zabezpieczeń, które mają więcej nowoczesnych języków, takich jak C#. Kompilator C# dałby błąd, że używasz nieprzypisanej zmiennej. C nie obchodzi. Nie ochroni cię przed samym sobą.

+5

Ta inicjalizacja, a nie przypisanie. –

+5

Ponadto, możliwość odnoszenia się do zmiennej w celu jej zainicjowania jest * użyteczna *, ponieważ możesz wziąć jej adres, jak w 'int x = initialize_and_register (& x)'. (Ten typ wywołania zwykle byłby spakowany w makro.) – user4815162342

+0

@ user4815162342 prawda, to oczywiście ma sens. Powinienem lepiej wybrać moje słowa :( – evanmcdonnal

-3

Jeśli

int c; 
c = c; 

zostanie skompilowany, nie widzę dlaczego int c = c; nie będzie skompilować.

+7

Dwa wyglądają na zwodniczo podobne, ale w rzeczywistości są raczej różne: 'int c = ...' to inicjalizacja, a nie przypisanie. Na przykład 'int c [] = {1, 2, 3};' działa, ale '{1, 2, 3}' nie jest poprawne w kontekście przypisania. – delnan

5

Jest całkowicie uzasadnione użycie zmiennej we własnym inicjatorze. Rozważmy połączonej listy:

#include <stdio.h> 
struct node { struct node *prev, *next; int value; }; 
int main() { 
    struct node l[] = {{0, l + 1, 42}, {l, l + 2, 5}, {l, 0, 99}}; 
    for (struct node *n = l; n; n = n->next) 
     printf("%d\n", n->value); 
    return 0; 
} 

w ogóle, diagnozowania, gdy wartość jest używana zainicjalizowana jest trudnym problemem; chociaż niektóre kompilatory mogą je wykryć, w niektórych przypadkach nie ma sensu wymagać, aby tak się stało.

+0

Jak nieokreślone zachowanie jest uzasadnione? – rubenvb

+8

To nie jest inicjalizacja zmiennej samej w sobie, ale raczej wskaźnik do niej samej, ponieważ 'l' rozpada się na wskaźnik' & [0] 'w tym kontekście. –

+0

Więc to jest zdefiniowane? – this

Powiązane problemy