Gdzie jest używane słowo kluczowe C auto?

104

Na studiach czytałem o tym autosłowie kluczowym iz biegiem czasu właściwie zapomniałem, co to jest. Jest definiowany jako:

definiuje zmienną lokalną jako posiadającą lokalny okres istnienia

Nigdy nie stwierdziłem, że jest nigdzie używany, czy naprawdę jest używany, a jeśli tak, to gdzie jest używany i w jakich przypadkach?

Vijay
źródło

Odpowiedzi:

90

autojest modyfikatorem, takim jak static. Definiuje klasę przechowywania zmiennej. Jednak ponieważ wartość domyślna dla zmiennych lokalnych to auto, zwykle nie trzeba jej ręcznie określać.

Ta strona zawiera listę różnych klas pamięci w C.

Mehrdad Afshari
źródło
13
Właśnie patrzyłem na to ponownie po tym, jak ktoś pozytywnie zagłosował na moją odpowiedź. Mówisz, że „normalnie nie musisz tego ręcznie określać”. Muszę tylko zapytać: czy rzeczywiście istnieje okoliczność, w której auto można określić, ale nie nastąpi to domyślnie?
Jerry Coffin
2
@JerryCoffin Not in C. W C ++ 11 jest zmieniony i można go używać do efektywnego wnioskowania o typie zmiennej lokalnej.
Mehrdad Afshari
2
Jednym z możliwych zastosowań jest deklaracja w przód funkcji zagnieżdżonych w GNU C - chociaż jest to przejęcie oryginalnej definicji auto. tigcc.ticalc.org/doc/keywords.html#auto
josiah,
2
Strona, do której prowadzi łącze, jest nieaktualna. Od C11 dostępne są również _Thread_localszczegóły: en.cppreference.com/w/c/language/storage_duration i stackoverflow.com/a/14289720/6557621
MCCCS
132

Jeśli przeczytałeś listę IAQ (rzadko zadawane pytania), wiedziałbyś, że auto jest przydatne przede wszystkim do definiowania lub deklarowania pojazdu:

auto my_car;

Pojazd, który konsekwentnie parkuje na zewnątrz:

extern auto my_car;

Dla tych, którym brakuje poczucia humoru i chcą „tylko faktów proszę pani”: krótka odpowiedź brzmi: nigdy nie ma żadnego powodu, by używać auto. Możesz używać autotylko zmiennej, która ma już autoklasę pamięci, więc po prostu określasz coś, co i tak by się stało. Próba użycia autodowolnej zmiennej, która nie ma jeszcze autoklasy pamięci, spowoduje odrzucenie kodu przez kompilator. Przypuszczam, że jeśli chcesz uzyskać informacje techniczne, Twoja implementacja nie musi być kompilatorem (ale tak jest) i teoretycznie może kontynuować kompilację kodu po wydaniu diagnostyki (ale nie będzie).

Mały dodatek autorstwa kaz :

Jest również:

static auto my_car;

co wymaga diagnostyki wg ISO C. To prawda, bo deklaruje, że auto jest zepsute. Diagnostyka jest bezpłatna, ale wyłączenie lampki na desce rozdzielczej kosztuje osiemdziesiąt dolarów. (Dwadzieścia lub mniej, jeśli kupisz własny klucz USB do diagnostyki pokładowej w serwisie eBay).

Wymienione wyżej extern auto my_carrównież wymaga diagnostyki iz tego powodu nigdy nie jest uruchamiane przez kompilator inaczej niż przez pracowników miejskich zajmujących się egzekwowaniem przepisów parkingowych.

Jeśli widzisz dużo extern static auto ...w jakiejkolwiek bazie kodu, jesteś w złym sąsiedztwie; natychmiast poszukaj lepszej pracy, zanim całe miejsce zmieni się w Rust.

Jerry Coffin
źródło
@self .: Wydaje się, że ISO nie zna „ISO 2011”. Jak myślisz, co to może ujednolicić?
Jerry Coffin
6
Dobrze, że nie miałem w ustach kawy, coli, stouta ani innego ciemnego płynu. Byłbyś mi winien ekran komputera, @JerryCoffin, gdyby tak było. NAJLEPSZA ODPOWIEDŹ!
David Hammen
2
@Dan: Naprawdę zajęło ci "sporo czasu" przeczytanie 5 linijek tekstu i przejście do części, w której jest napisane: "Krótka odpowiedź brzmi: nigdy nie ma żadnego powodu, aby używać auto"? Poważnie? Biorąc pod uwagę komentarz bezpośrednio poprzedzający Twój, wydaje się, że przynajmniej kilka osób uważa go za pozytywny wkład.
Jerry Coffin
@JerryCoffin Już to wyjaśniłem, przeczytaj mój komentarz ponownie. Z perspektywy czasu jest 20/20.
Dan Bechard
2
Niedawno minąłem poważny pożar (zamknięte dwa pasy), który sugeruje potrzebęchar auto my_car;
ostry
46

Słowo autokluczowe jest bezużyteczne w języku C. Jest tak, ponieważ przed językiem C istniał język B, w którym to słowo kluczowe było niezbędne do deklarowania zmiennych lokalnych. (B rozwinęło się w NB, które stało się C).

Oto instrukcja odniesienia dla B .

Jak widać, podręcznik jest bogaty w przykłady, w jakich autojest używany. Dzieje się tak, ponieważ nie ma intsłowa kluczowego. Potrzebny jest jakiś rodzaj słowa kluczowego, aby powiedzieć „to jest deklaracja zmiennej”, a to słowo kluczowe wskazuje również, czy jest to lokalna, czy zewnętrzna ( autoversus extrn). Jeśli nie używasz jednego lub drugiego, masz błąd składniowy. Oznacza to, że x, y;nie jest deklaracją samą w sobie, ale auto x, y;jest.

Ponieważ podstawy kodu napisane w B musiały zostać przeniesione do NB i C w miarę rozwoju języka, nowsze wersje języka niosły pewien bagaż dla poprawy kompatybilności wstecznej, co przekładało się na mniej pracy. W przypadku programu autoprogramiści nie musieli wytropić każdego wystąpienia autoi go usunąć.

Z podręcznika jasno wynika, że ​​obecnie przestarzały cruft „implicit int” w C (możliwość pisania main() { ... }bez żadnego intz przodu) również pochodzi z B. To kolejna funkcja wstecznej kompatybilności obsługująca kod B. Funkcje nie mają typu zwracanego określonego w B, ponieważ nie ma typów. Wszystko jest słowem, jak w wielu językach asemblera.

Zwróć uwagę, jak funkcja może być po prostu zadeklarowana, extrn putchara następnie jedyna rzecz, która czyni ją funkcją używaną przez identyfikator : jest używana w wyrażeniu wywołania funkcji, takim jak putchar(x), i to właśnie mówi kompilatorowi, aby traktował to słowo bez typu jako wskaźnik funkcji.

Kaz
źródło
24

W C autojest słowem kluczowym, które wskazuje, że zmienna jest lokalna dla bloku. Ponieważ jest to wartość domyślna dla zmiennych o zasięgu blokowym, jest niepotrzebna i bardzo rzadko używana (nie sądzę, żebym kiedykolwiek widziała jej użycie poza przykładami w tekstach omawiających słowo kluczowe). Byłbym zainteresowany, gdyby ktoś mógł wskazać przypadek, w którym użycie autobyło wymagane do uzyskania poprawnej analizy lub zachowania.

Jednak w standardzie C ++ 11 autosłowo kluczowe zostało `` przejęte '' w celu obsługi wnioskowania o typie, gdzie typ zmiennej można pobrać z typu jej inicjatora:

auto someVariable = 1.5;   // someVariable will have type double

Wnioskowanie o typie jest dodawane głównie w celu obsługi deklarowania zmiennych w szablonach lub zwracanych z funkcji szablonu, gdzie typy oparte na parametrach szablonu (lub wywnioskowane przez kompilator podczas tworzenia wystąpienia szablonu) często mogą być dość uciążliwe do ręcznego zadeklarowania.

Michael Burr
źródło
1
„Zmienna jest lokalna dla bloku” - to wcale nie jest prawda. Wszystkie zmienne zadeklarowane w bloku są lokalne dla tego bloku (w odniesieniu do zakresu). Mogą być powiązane z innymi zmiennymi w programie, ale deklaracja jest widoczna tylko w tym bloku. autodotyczy klasy pamięci, która nie ma nic wspólnego z widocznością.
fuz
12

W starym kompilatorze Aztec C możliwe było przekształcenie wszystkich zmiennych automatycznych w zmienne statyczne (w celu zwiększenia szybkości adresowania) za pomocą przełącznika wiersza polecenia.

Ale zmienne wyraźnie zadeklarowane za pomocą autozostały w tym przypadku pozostawione bez zmian. (Konieczność dla funkcji rekurencyjnych, które w innym przypadku nie działałyby poprawnie!)

raphnet
źródło
7

Słowo autokluczowe jest podobne do włączania średników w Pythonie, było wymagane przez poprzedni język ( B), ale programiści zdali sobie sprawę, że jest zbędne, ponieważ większość rzeczy było auto.

Podejrzewam, że pozostawiono go, aby pomóc w przejściu z B do C. Krótko mówiąc, jednym z zastosowań jest zgodność z językiem B.

Na przykład w B i 80s C:

/* The following function will print a non-negative number, n, to
   the base b, where 2<=b<=10.  This routine uses the fact that
   in the ASCII character set, the digits 0 to 9 have sequential
   code values.  */

printn(n, b) {
        extrn putchar;
        auto a;

        if (a = n / b)        /* assignment, not test for equality */
                printn(a, b); /* recursive */
        putchar(n % b + '0');
}
Michaił
źródło
1

Słowo kluczowe Auto to przykład klasy pamięci (pewnego rodzaju techniki, która decyduje o czasie życia zmiennej i miejscu przechowywania). Ma zachowanie, w wyniku którego zmienna utworzona przez Pomoc tego słowa kluczowego ma długość życia (czas życia) znajduje się tylko w nawiasach klamrowych

{
    auto int x=8;        
    printf("%d",x);  // here x is 8

    { 
        auto int x=3;
        printf("%d",x);  // here x is 3
    }              

    printf("%d",x);  // here x is 8
}          
Atul Sharma
źródło
1

automoże być używany tylko dla zmiennych o zasięgu blokowym. extern auto intjest bzdurą, ponieważ kompilator nie może określić, czy używa zewnętrznej definicji, czy też nadpisać extern definicją automatyczną (również auto i extern to zupełnie inne czasy przechowywania, na przykład static auto int, co oczywiście jest również bzdurą). Zawsze może zinterpretować to w jeden sposób, ale zamiast tego traktuje to jako błąd.

Jest jedna funkcja, która autoto zapewnia i która umożliwia zastosowanie reguły „wszystko jest int” wewnątrz funkcji. Inaczej niż poza funkcją, gdzie a=3jest interpretowane jako definicja, int a =3ponieważ przypisania nie istnieją w zakresie pliku, a=3jest to błąd wewnątrz funkcji, ponieważ najwyraźniej kompilator zawsze interpretuje to jako przypisanie do zmiennej zewnętrznej, a nie definicję (nawet jeśli Brak extern int aterminowe deklaracje w funkcji lub w zakresie plików), ale specifier jak static, const, volatileczy autooznaczałoby, że jest to definicja i kompilator wykonuje go jako definicji, z wyjątkiem autonie ma skutków ubocznych innych specyfikatorów. auto a=3jest zatem pośrednioauto int a = 3 . Wprawdzie,signed a = 3ma ten sam efekt i unsigned a = 3zawsze jest intem bez znaku.

Należy również zauważyć, że `` autonie ma wpływu na to, czy obiekt zostanie przydzielony do rejestru (chyba że jakiś konkretny kompilator zwróci na to uwagę, ale wydaje się to mało prawdopodobne) ''

Lewis Kelsey
źródło
-1

Jestem pewien, że znasz specyfikatory klasy pamięci w C, którymi są „extern”, „static”, „register” i „auto”. Definicja „auto” jest prawie podana w innych odpowiedziach, ale tutaj jest możliwe użycie słowa kluczowego „auto”, którego nie jestem pewien, ale myślę, że jest zależne od kompilatora. Widzisz, w odniesieniu do specyfikatorów klas pamięci istnieje reguła. Nie możemy użyć wielu specyfikatorów klasy pamięci dla zmiennej. Z tego powodu statyczne zmienne globalne nie mogą być zewnętrzne. Dlatego są znane tylko w ich aktach. Po przejściu do ustawień kompilatora możesz włączyć flagę optymalizacji dla szybkości. jednym ze sposobów optymalizacji kompilatora jest szuka zmiennych bez specyfikatorów klasy pamięci, a następnie dokonuje oceny na podstawie dostępności pamięci podręcznej i kilku innych czynników, aby zobaczyć, czy powinien traktować tę zmienną przy użyciu specyfikatora rejestru, czy nie. A co, jeśli chcemy zoptymalizować nasz kod pod kątem szybkości, wiedząc, że określona zmienna w naszym programie nie jest bardzo ważna i nie chcemy, aby kompilator nawet traktował ją jako rejestr. Mimo to, ustawiając auto, kompilator nie będzie mógł dodać specyfikatora rejestru do zmiennej od wpisania "register auto int a;" LUB "auto register int a;" podnosi błąd używania wielu specyfikatorów klas pamięci. Podsumowując, pomyślałem, że auto może zabronić kompilatorowi traktowania zmiennej jako rejestru poprzez optymalizację. co, jeśli chcemy zoptymalizować nasz kod pod kątem szybkości, wiedząc, że określona zmienna w naszym programie nie jest bardzo ważna i nie chcemy, aby kompilator nawet traktował ją jako rejestr. Mimo to, ustawiając auto, kompilator nie będzie mógł dodać specyfikatora rejestru do zmiennej od wpisania "register auto int a;" LUB "auto register int a;" podnosi błąd używania wielu specyfikatorów klas pamięci. Podsumowując, pomyślałem, że auto może zabronić kompilatorowi traktowania zmiennej jako rejestru poprzez optymalizację. co, jeśli chcemy zoptymalizować nasz kod pod kątem szybkości, wiedząc, że określona zmienna w naszym programie nie jest bardzo ważna i nie chcemy, aby kompilator nawet traktował ją jako rejestr. Mimo to, ustawiając auto, kompilator nie będzie mógł dodać specyfikatora rejestru do zmiennej od wpisania "register auto int a;" LUB "auto register int a;" podnosi błąd używania wielu specyfikatorów klas pamięci. Podsumowując, pomyślałem, że auto może zabronić kompilatorowi traktowania zmiennej jako rejestru poprzez optymalizację. podnosi błąd używania wielu specyfikatorów klas pamięci. Podsumowując, pomyślałem, że auto może zabronić kompilatorowi traktowania zmiennej jako rejestru poprzez optymalizację. podnosi błąd używania wielu specyfikatorów klas pamięci. Podsumowując, pomyślałem, że auto może zabronić kompilatorowi traktowania zmiennej jako rejestru poprzez optymalizację.

Ta teoria nie działa dla kompilatora GCC, jednak nie próbowałem innych kompilatorów.

Alireza Mirghasemi
źródło