Wo wird das Schlüsselwort C auto verwendet?

104

In meinen College-Tagen habe ich über das autoSchlüsselwort gelesen und im Laufe der Zeit tatsächlich vergessen, was es ist. Es ist definiert als:

definiert eine lokale Variable als lokal variabel

Ich habe nie festgestellt, dass es irgendwo verwendet wird, wird es wirklich verwendet und wenn ja, wo wird es verwendet und in welchen Fällen?

Vijay
quelle

Antworten:

90

autoist ein Modifikator wie static. Es definiert die Speicherklasse einer Variablen. Da der Standard für lokale Variablen jedoch ist auto, müssen Sie ihn normalerweise nicht manuell angeben.

Diese Seite listet verschiedene Speicherklassen in C auf.

Mehrdad Afshari
quelle
13
Ich habe mir das gerade noch einmal angesehen, nachdem jemand meine Antwort hochgestimmt hat. Sie sagen, Sie müssen es normalerweise nicht manuell angeben. Ich muss nur fragen: Gibt es tatsächlich einen Umstand, unter dem angegeben werden auto kann , der jedoch nicht standardmäßig auftritt?
Jerry Coffin
2
@JerryCoffin Nicht in C. In C ++ 11 wird es neu verwendet und Sie können es verwenden, um effektiv auf lokale Variablentypen zu schließen.
Mehrdad Afshari
2
Eine mögliche Verwendung ist die Vorwärtsdeklaration verschachtelter Funktionen in GNU C - obwohl dies eine Entführung der ursprünglichen Definition von ist auto. tigcc.ticalc.org/doc/keywords.html#auto
josiah
2
Die verlinkte Seite ist veraltet. Seit C11 gibt es auch _Thread_localDetails: en.cppreference.com/w/c/language/storage_duration und stackoverflow.com/a/14289720/6557621
MCCCS
132

Wenn Sie die IAQ- Liste (Infrequently Asked Questions) gelesen haben , wissen Sie, dass auto in erster Linie nützlich ist, um ein Fahrzeug zu definieren oder zu deklarieren:

auto my_car;

Ein Fahrzeug, das konsequent im Freien geparkt wird:

extern auto my_car;

Für diejenigen, die keinen Sinn für Humor haben und "nur die Fakten Ma'am" wollen: Die kurze Antwort lautet, dass es keinen Grund gibt, überhaupt etwas zu verwenden auto. Sie dürfen nur autoeine Variable verwenden, die bereits über eine autoSpeicherklasse verfügt. Sie geben also nur etwas an, das sowieso passieren würde. Wenn Sie versuchen, autoeine Variable zu verwenden, für die die autoSpeicherklasse noch nicht vorhanden ist, lehnt der Compiler Ihren Code ab. Ich nehme an, wenn Sie technisch werden möchten, muss Ihre Implementierung kein Compiler sein (aber es ist) und sie kann den Code theoretisch nach dem Ausstellen einer Diagnose weiter kompilieren (wird es aber nicht).

Kleiner Nachtrag von kaz :

Es gibt auch:

static auto my_car;

Dies erfordert eine Diagnose gemäß ISO C. Dies ist richtig, da es erklärt, dass das Auto eine Panne hat. Die Diagnose ist kostenlos, aber das Ausschalten der Armaturenbrettbeleuchtung kostet Sie achtzig Dollar. (20 oder weniger, wenn Sie Ihren eigenen USB-Dongle für die On-Board-Diagnose bei eBay kaufen).

Das oben Genannte extern auto my_carerfordert auch eine Diagnose, und aus diesem Grund wird es nie durch den Compiler ausgeführt, außer von städtischen Mitarbeitern, die mit der Parküberwachung beauftragt sind.

Wenn Sie extern static auto ...in einer Codebasis viel sehen , befinden Sie sich in einer schlechten Nachbarschaft. Suchen Sie sofort nach einem besseren Job, bevor sich der ganze Ort Rust zuwendet.

Jerry Sarg
quelle
@self.: Die ISO scheint keine "ISO 2011" zu kennen. Was glaubst du, könnte es standardisieren?
Jerry Coffin
6
Es ist gut, dass ich keinen Kaffee, Cola, Stout oder eine andere dunkle Flüssigkeit in meinem Mund hatte. Sie würden mir einen Computerbildschirm schulden, @JerryCoffin, wenn das der Fall wäre. Beste Antwort aller Zeiten!
David Hammen
2
@Dan: Ehrlich gesagt haben Sie "eine ganze Weile" gebraucht, um 5 Textzeilen zu lesen und zu dem Teil zu gelangen, in dem es heißt: "Die kurze Antwort ist, dass es nie einen Grund gibt, Auto überhaupt zu verwenden"? Ernsthaft? Angesichts des Kommentars unmittelbar vor Ihrem scheint es, dass zumindest einige Leute einen positiven Beitrag finden.
Jerry Coffin
@ JerryCoffin Ich habe das bereits erklärt, lies meinen Kommentar noch einmal. Rückblick ist 20/20.
Dan Bechard
2
Ich ging vor kurzem eine schwere Feuersbrunst (zwei Fahrspuren geschlossen) , die für einen Bedarf schon sagtchar auto my_car;
splitter
46

Das autoSchlüsselwort ist in der C-Sprache nutzlos. Es ist da, weil es vor der C-Sprache eine B-Sprache gab, in der dieses Schlüsselwort für die Deklaration lokaler Variablen erforderlich war. (B wurde zu NB entwickelt, was zu C wurde).

Hier ist das Referenzhandbuch für B .

Wie Sie sehen können, enthält das Handbuch zahlreiche Beispiele, in denen autoverwendet wird. Dies liegt daran, dass kein intSchlüsselwort vorhanden ist. Es wird eine Art Schlüsselwort benötigt, um zu sagen, dass dies eine Deklaration einer Variablen ist, und dieses Schlüsselwort gibt auch an, ob es sich um eine lokale oder eine externe Variable handelt ( autoversus extrn). Wenn Sie das eine oder andere nicht verwenden, liegt ein Syntaxfehler vor. Das heißt, x, y;ist keine Erklärung für sich, sondern auto x, y;ist.

Da in B geschriebene Codebasen bei der Entwicklung der Sprache nach NB und C portiert werden mussten, enthielten die neueren Versionen der Sprache etwas Gepäck für eine verbesserte Abwärtskompatibilität, was zu weniger Arbeit führte. Im Fall von automussten die Programmierer nicht jedes Vorkommen aufspüren autound entfernen.

Aus dem Handbuch geht hervor, dass die mittlerweile veraltete "implizite int" -Kruft in C (die in der Lage ist, main() { ... }ohne intFront zu schreiben ) ebenfalls von B stammt. Dies ist eine weitere Abwärtskompatibilitätsfunktion zur Unterstützung von B-Code. Für Funktionen ist in B kein Rückgabetyp angegeben, da keine Typen vorhanden sind. Alles ist ein Wort, wie in vielen Assemblersprachen.

Beachten Sie, wie eine Funktion nur deklariert werden kann extrn putcharund dann das einzige, was sie zu einer Funktion macht, die der Bezeichner verwendet : Sie wird in einem Funktionsaufrufausdruck wie verwendet putchar(x), und das sagt dem Compiler, dass er dieses typenlose Wort als Funktionszeiger behandeln soll.

Kaz
quelle
24

In C autoist ein Schlüsselwort, das angibt, dass eine Variable für einen Block lokal ist. Da dies die Standardeinstellung für Variablen mit Blockbereich ist, ist sie unnötig und wird sehr selten verwendet (ich glaube nicht, dass ich sie jemals außerhalb von Beispielen in Texten gesehen habe, in denen das Schlüsselwort behandelt wird). Es würde mich interessieren, ob jemand auf einen Fall hinweisen könnte, in dem die Verwendung von autoerforderlich war, um eine korrekte Analyse oder ein korrektes Verhalten zu erzielen.

Im C ++ 11-Standard wurde das autoSchlüsselwort jedoch zur Unterstützung der Typinferenz "entführt", wobei der Typ einer Variablen dem Typ ihres Initialisierers entnommen werden kann:

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

Typinferenz wird hauptsächlich hinzugefügt, um das Deklarieren von Variablen in Vorlagen zu unterstützen oder von Vorlagenfunktionen zurückgegeben zu werden, bei denen das manuelle Deklarieren von Typen, die auf einem Vorlagenparameter basieren (oder vom Compiler abgeleitet werden, wenn eine Vorlage instanziiert wird), oft sehr schmerzhaft sein kann.

Michael Burr
quelle
1
"Die Variable ist lokal für einen Block" - das stimmt überhaupt nicht. Alle in einem Block deklarierten Variablen sind lokal für diesen Block (in Bezug auf den Bereich). Sie können mit anderen Variablen im Programm verknüpft sein, aber die Deklaration ist nur in diesem Block sichtbar. autohandelt von einer Speicherklasse, die nichts mit Sichtbarkeit zu tun hat.
Fuz
12

Mit dem alten Aztec C-Compiler war es möglich, alle automatischen Variablen mithilfe eines Befehlszeilenschalters in statische Variablen umzuwandeln (um die Adressierungsgeschwindigkeit zu erhöhen).

autoIn diesem Fall wurden explizit mit deklarierte Variablen unverändert gelassen. (Ein Muss für rekursive Funktionen, die sonst nicht richtig funktionieren würden!)

Raphnet
quelle
7

Das autoSchlüsselwort ähnelt dem Einfügen von Semikolons in Python. Es wurde von einer früheren Sprache ( B) benötigt, aber die Entwickler erkannten, dass es redundant war, da die meisten Dinge vorhanden waren auto.

Ich vermute, es wurde gelassen, um beim Übergang von B nach C zu helfen. Kurz gesagt, eine Verwendung ist die Kompatibilität der B-Sprache.

Zum Beispiel in B und 80er 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');
}
Mikhail
quelle
1

Das Auto-Schlüsselwort ist ein Beispiel für eine Speicherklasse (eine Art von Techniken, die die Lebensdauer der Variablen und des Speicherorts bestimmen). Es hat ein Verhalten, bei dem Variablen, die mithilfe der Hilfe dieses Schlüsselworts erstellt wurden, die Lebensdauer (Lebensdauer) nur in geschweiften Klammern haben

{
    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
quelle
0

autokann nur für Variablen mit Blockbereich verwendet werden. extern auto intist Müll, weil der Compiler nicht bestimmen kann, ob dies eine externe Definition verwendet oder ob das Externe mit einer Auto-Definition überschrieben werden soll (auch Auto und Extern sind völlig unterschiedliche Speicherdauern, wie static auto int, was natürlich auch Müll ist). Es könnte sich immer dafür entscheiden, es in eine Richtung zu interpretieren, sondern es stattdessen als Fehler zu behandeln.

Es gibt eine Funktion, autodie die Regel "Alles ist ein Int" innerhalb einer Funktion aktiviert. Anders als außerhalb einer Funktion, wo a=3sie als Definition interpretiert wird, int a =3weil Zuweisungen im Dateibereich nicht vorhanden sind, a=3ist dies ein Fehler innerhalb einer Funktion, da der Compiler sie anscheinend immer als Zuweisung zu einer externen Variablen und nicht als Definition interpretiert (selbst wenn vorhanden) sind keine extern int aVorwärtsdeklarationen in der Funktion oder in der Datei scope), sondern ein Spezifizierer wie static, const, volatileoder autowürde bedeuten , dass es sich um eine Definition und der Compiler nimmt , ist es als eine Definition, mit der Ausnahme autonicht die Nebenwirkungen der anderen Planer hat. auto a=3ist daher implizit auto int a = 3. Freilich,signed a = 3hat den gleichen Effekt und unsigned a = 3ist immer ein int ohne Vorzeichen.

Beachten Sie auch: " autoHat keinen Einfluss darauf, ob ein Objekt einem Register zugewiesen wird (es sei denn, ein bestimmter Compiler beachtet es, aber das scheint unwahrscheinlich)."

Lewis Kelsey
quelle
-1

Ich bin sicher, dass Sie mit Speicherklassenspezifizierern in C vertraut sind, die "extern", "statisch", "register" und "auto" sind. Die Definition von "auto" wird in anderen Antworten ziemlich häufig angegeben, aber hier ist eine mögliche Verwendung des Schlüsselworts "auto", die ich nicht sicher bin, aber ich denke, dass sie vom Compiler abhängig ist. Sie sehen, in Bezug auf Speicherklassenspezifizierer gibt es eine Regel. Wir können nicht mehrere Speicherklassenspezifizierer für eine Variable verwenden. Aus diesem Grund können statische globale Variablen nicht extern bereitgestellt werden. Daher sind sie nur ihrer Datei bekannt. Wenn Sie zu Ihrer Compilereinstellung gehen, können Sie das Optimierungsflag für die Geschwindigkeit aktivieren. Eine der Möglichkeiten, die der Compiler optimiert, ist: Es sucht nach Variablen ohne Speicherklassenspezifizierer und führt dann eine Bewertung basierend auf der Verfügbarkeit des Cache-Speichers und einigen anderen Faktoren durch, um festzustellen, ob diese Variable mit dem Registerspezifizierer behandelt werden soll oder nicht. Was ist nun, wenn wir unseren Code auf Geschwindigkeit optimieren möchten, während wir wissen, dass eine bestimmte Variable in unserem Programm nicht sehr wichtig ist und wir nicht möchten, dass der Compiler sie überhaupt als Register betrachtet. Wenn Sie jedoch auto setzen, kann der Compiler einer Variablen keinen Registerspezifizierer hinzufügen, da Sie "register auto int a" eingeben. ODER "Auto Register Int Int;" löst den Fehler aus, mehrere Speicherklassenspezifizierer zu verwenden. Zusammenfassend dachte ich, dass Auto dem Compiler verbieten kann, eine Variable durch Optimierung als Register zu behandeln. Was ist, wenn wir unseren Code auf Geschwindigkeit optimieren möchten, während wir wissen, dass eine bestimmte Variable in unserem Programm nicht sehr wichtig ist und wir nicht möchten, dass der Compiler sie überhaupt als Register betrachtet? Wenn Sie jedoch auto setzen, kann der Compiler einer Variablen keinen Registerspezifizierer hinzufügen, da Sie "register auto int a" eingeben. ODER "Auto Register Int Int;" löst den Fehler aus, mehrere Speicherklassenspezifizierer zu verwenden. Zusammenfassend dachte ich, dass Auto dem Compiler verbieten kann, eine Variable durch Optimierung als Register zu behandeln. Was ist, wenn wir unseren Code auf Geschwindigkeit optimieren möchten, während wir wissen, dass eine bestimmte Variable in unserem Programm nicht sehr wichtig ist und wir nicht möchten, dass der Compiler sie überhaupt als Register betrachtet? Wenn Sie jedoch auto setzen, kann der Compiler einer Variablen keinen Registerspezifizierer hinzufügen, da Sie "register auto int a" eingeben. ODER "Auto Register Int Int;" löst den Fehler aus, mehrere Speicherklassenspezifizierer zu verwenden. Zusammenfassend dachte ich, dass Auto dem Compiler verbieten kann, eine Variable durch Optimierung als Register zu behandeln. löst den Fehler aus, mehrere Speicherklassenspezifizierer zu verwenden. Zusammenfassend dachte ich, dass Auto dem Compiler verbieten kann, eine Variable durch Optimierung als Register zu behandeln. löst den Fehler aus, mehrere Speicherklassenspezifizierer zu verwenden. Zusammenfassend dachte ich, dass Auto dem Compiler verbieten kann, eine Variable durch Optimierung als Register zu behandeln.

Diese Theorie hat für den GCC-Compiler nicht funktioniert, ich habe jedoch keine anderen Compiler ausprobiert.

Alireza Mirghasemi
quelle