Kod:
int main(void)
{
auto a=1;
return 0;
}
jest kompilowany bez błędów przez kompilator MS Visual Studio 2012, gdy plik ma rozszerzenie .c. Zawsze uważałem, że kiedy używasz rozszerzenia .c, kompilacja powinna być zgodna ze składnią C, a nie C ++. Ponadto, o ile wiem, auto bez typu jest dozwolone tylko w C ++ od C ++ 11, gdzie oznacza to, że typ jest wywnioskowany z inicjatora.
Czy to oznacza, że mój kompilator nie trzyma się języka C, czy też kod faktycznie jest poprawny w języku C?
int
został usunięty ze standardu C w 1999 roku.Odpowiedzi:
auto
to stare słowo kluczowe C, które oznacza „zasięg lokalny”.auto a
jest tym samym coauto int a
, a ponieważ zasięg lokalny jest domyślny dla zmiennej zadeklarowanej wewnątrz funkcji, jest również taki sam jakint a
w tym przykładzie.To słowo kluczowe jest właściwie pozostałością po poprzedniku B C, gdzie nie było typów podstawowych: wszystko było
int
, wskaźnik doint
, tablicaint
. (*) Deklaracje byłyby alboauto
alboextrn
[sic]. C odziedziczył „wszystko jestint
” jako domyślną regułę, więc możesz deklarować liczby całkowite za pomocąISO C pozbyło się tego, ale wiele kompilatorów nadal akceptuje to ze względu na kompatybilność wsteczną. Jeśli wydaje ci się to nieznane, powinieneś zdać sobie sprawę, że działa powiązana reguła
co jest nadal powszechne we współczesnym kodzie.
C ++ 11 ponownie użyło słowa kluczowego, którego niewielu programistów C ++ używało w oryginalnym znaczeniu do wnioskowania o typie. Jest to w większości bezpieczne, ponieważ
int
reguła „wszystko jest ” z C została już usunięta w C ++ 98; jedyną rzeczą, która się psuje, jest toauto T a
, czego i tak nikt nie używał. (Gdzieś w swoich artykułach na temat historii języka Stroustrup komentuje to, ale nie mogę teraz znaleźć dokładnego odniesienia.)(*) Obsługa łańcuchów w B była interesująca: używałbyś tablic składających się z
int
wielu znaków i pakował je w każdy element członkowski. B był faktycznie BCPL z inną składnią.źródło
-Werror
.To jest zarówno odpowiedź, jak i rozszerzony komentarz do Nie, to nie jest legalne od 1999 roku. Żaden przyzwoity nowoczesny kompilator C na to nie pozwala.
Tak,
auto a=1;
jest nielegalne w C1999 (a także w C2011). To, że jest to teraz nielegalne, nie oznacza, że nowoczesny kompilator C powinien odrzucać kod zawierający takie konstrukcje. Twierdziłbym dokładnie odwrotnie, że przyzwoity, nowoczesny kompilator C musi na to nadal pozwalać.Zarówno clang, jak i gcc robią to właśnie podczas kompilowania przykładowego kodu w pytaniu względem wersji standardu z 1999 lub 2011 roku. Obaj kompilatorzy wydają diagnostykę, a następnie kontynuują tak, jakby było to stwierdzenie budzące zastrzeżenia
auto int a=1;
.Moim zdaniem to właśnie powinien robić porządny kompilator. Wydając diagnostykę, clang i gcc są w pełni zgodne ze standardem. Standard nie mówi, że kompilator musi odrzucać nielegalny kod. Norma mówi jedynie, że zgodna implementacja musi generować co najmniej jeden komunikat diagnostyczny, jeśli jednostka tłumacząca zawiera naruszenie jakiejkolwiek reguły składniowej lub ograniczenia (5.1.1.3).
Biorąc pod uwagę kod, który zawiera niedozwolone konstrukcje, każdy przyzwoity kompilator spróbuje zrozumieć niedozwolony kod, aby kompilator mógł znaleźć następny błąd w kodzie. Kompilator, który zatrzymuje się przy pierwszym błędzie, nie jest zbyt dobrym kompilatorem. Istnieje sposób, aby wyciągnąć z tego sens
auto a=1
, który polega na zastosowaniu reguły „implicit int”. Ta reguła wymusza na kompilatorze interpretacjęauto a=1
tak, jakby miała miejsce,auto int a=1
gdy kompilator jest używany w trybie C90 lub K&R.Większość kompilatorów zazwyczaj odrzuca kod (odrzucenie: odmowa wygenerowania pliku obiektowego lub pliku wykonywalnego), który zawiera niedozwoloną składnię. Jest to przypadek, w którym autorzy kompilatora zdecydowali, że niepowodzenie kompilacji nie jest najlepszą opcją. Najlepiej przeprowadzić diagnostykę, naprawić kod i kontynuować. Jest po prostu zbyt wiele starszego kodu, który jest usiany konstrukcjami takimi jak
register a=1;
. Kompilator powinien móc skompilować ten kod w trybie C99 lub C11 (oczywiście z diagnostyką).źródło
-ffs-please-stop-allowing-constructs-from-some-previous-millennium
opcji kompilatora lub, bardziej zwięźle,-fstrict-compliance
opcji. Narzekanie na kompilator: „Kiedy użyłem -std = c11, nie spodziewałem się, że starożytny kruft K&R się skompiluje. Tak naprawdę chciałem, żeby się nie kompilował!”-std=c99
bycie bardziej restrykcyjnym byłoby krokiem we właściwym kierunku :)gcc -g -O3 -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror
(czego używam rutynowo, nawet w kodzie z pytań na SO), wtedy zbliżasz się do tego, czego chcesz. Chciałbym, aby GCC domyślnie ustawiało przynajmniej-std=c99
i najlepiej-std=c11
(lub,-std=gnu11
bardziej prawdopodobne jest, że to zrobią), ale do tego czasu… Możesz modyfikować te opcje;-pedantic
,-Wshadow
,-Wold-style-declaration
A inni mogą być przydatne, ale jest to dobry Zaczynając zestaw opcji.-pedantic-errors
auto
ma znaczenie zawarte w standardzie z 2011 r.C
iC++
przed nim. Oznacza to, że zmienna ma automatyczny czas życia, czyli czas życia określony przez zakres . Jest to przeciwieństwo np.static
Czasu życia, w którym zmienna trwa „wiecznie”, niezależnie od zakresu.auto
jest domyślnym okresem życia i prawie nigdy nie jest wyraźnie podawany. Dlatego zmiana znaczenia wC++
.Teraz
C
, przed standardem 99, jeśli nie określisz typu zmiennej, domyślnie jest toint
.Więc razem z
auto a = 1;
tobą deklarujesz (i definiujesz)int
zmienną, której czas życia jest określony przez zakres.(„żywotność” jest bardziej poprawnie nazywana „czasem przechowywania”, ale myślę, że jest to mniej jasne).
źródło
main
funkcji”.auto
istatic
są to jedyne dwie możliwości. Próbowałem napisać odpowiedź w sposób skierowany do pytającego, który wydaje się być całkiem nowy dlaC++
(iC
), więc trochę przemilczałem szczegóły. Może to był zły pomysł; wcześniej czy później trzeba je pokryć.int
treść jest usuwana z C od 1999 roku.W C i historycznych dialektach C ++
auto
jest słowem kluczowym oznaczającyma
automatyczne przechowywanie. Ponieważ można go zastosować tylko do zmiennych lokalnych, które są domyślnie automatyczne, nikt go nie używa; dlatego C ++ zmienił teraz przeznaczenie słowa kluczowego.Historycznie rzecz biorąc, C dopuszczał deklaracje zmiennych bez specyfikatora typu; domyślny typ to
int
. Więc ta deklaracja jest równoważnaMyślę, że jest to przestarzałe (i prawdopodobnie zabronione) w nowoczesnym C; ale niektóre popularne kompilatory domyślnie używają C90 (co, jak sądzę, na to zezwala) i, irytująco, włączają ostrzeżenia tylko wtedy, gdy specjalnie o nie poprosisz. Kompilacja z GCC i podanie C99 za pomocą
-std=c99
lub włączenie ostrzeżenia za pomocą-Wall
lub-Wimplicit-int
daje ostrzeżenie:źródło
W C
auto
oznacza to samo, coregister
w C ++ 11: oznacza, że zmienna ma automatyczny czas trwania.A w C przed C99 (a kompilator Microsoftu nie obsługuje ani C99, ani C11, chociaż może obsługiwać ich części), typ można pominąć w wielu przypadkach, w których będzie domyślnie
int
.W ogóle nie pobiera typu z inicjatora. Po prostu przypadkiem wybrałeś kompatybilny inicjator.
źródło
auto
iregister
miał dokładnie to samo znaczenie (wcześniej komentowałem, że istnieją ograniczenia w pobieraniuregister
adresu zmiennej -kwalifikowanej, ale było to niepoprawne dla C ++).register
, choć przestarzałe, zachowuje na razie swoje stare znaczenie.auto
w C oznacza to samo coregister
w C ++, co robi (oba oznaczają automatyczny czas przechowywania i nic więcej).Typ kompilacji programu Visual Studio jest dostępny pod adresem
right click on file -> Properties -> C/C++ -> Advanced -> Compile As
. Aby upewnić się, że jest skompilowana jako/TC
opcja wymuszona w C, w tym przypadku tak właśnie powiedział larsmans (stareauto
słowo kluczowe C ). Może zostać skompilowany jako C ++ bez Twojej wiedzy.źródło
Klasa pamięci definiuje zakres (widoczność) i czas życia zmiennych i / lub funkcji w programie w C.
Istnieją następujące klasy pamięci, których można używać w programie C.
auto
to domyślna klasa pamięci dla wszystkich zmiennych lokalnych.Powyższy przykład definiuje dwie zmienne z tą samą klasą pamięci. auto może być używane tylko w funkcjach, tj. zmiennych lokalnych.
int
jest domyślnym typemauto
w poniższym kodzie:Poniższy kod jest również legalny:
źródło