Der Code:
int main(void)
{
auto a=1;
return 0;
}
wird vom MS Visual Studio 2012-Compiler fehlerfrei kompiliert, wenn die Datei die Erweiterung .c hat. Ich habe immer gedacht, dass bei Verwendung der Erweiterung .c die Kompilierung nach der C-Syntax und nicht nach C ++ erfolgen sollte. Darüber hinaus ist, soweit ich weiß, Auto ohne Typ nur in C ++ seit C ++ 11 zulässig , was bedeutet, dass der Typ vom Initialisierer abgeleitet wird.
Bedeutet das, dass mein Compiler nicht an C festhält, oder ist der Code in C-Sprache tatsächlich korrekt?
int
wurde 1999 aus dem C-Standard entfernt.Antworten:
auto
ist ein altes C-Schlüsselwort, das "lokaler Bereich" bedeutet.auto a
ist dasselbe wieauto int a
und da der lokale Bereich der Standard für eine in einer Funktion deklarierte Variable ist, ist er auch der gleiche wieint a
in diesem Beispiel.Dieses Schlüsselwort ist eigentlich ein Überbleibsel von Cs Vorgänger B, wo es keine Basistypen gab: Alles war
int
, Zeiger aufint
, Array vonint
. (*) Deklarationen wären entwederauto
oderextrn
[sic]. C hatint
standardmäßig "alles ist " geerbt , sodass Sie Ganzzahlen mit deklarieren könnenISO C hat dies beseitigt, aber viele Compiler akzeptieren es aus Gründen der Abwärtskompatibilität immer noch. Wenn es Ihnen unbekannt vorkommt, sollten Sie sich darüber im Klaren sein, dass eine verwandte Regel in funktioniert
was im modernen Code immer noch üblich ist.
C ++ 11 verwendete das Schlüsselwort, das nur wenige C ++ - Programmierer mit der ursprünglichen Bedeutung verwendeten, für seine Typinferenz. Dies ist größtenteils sicher, da die
int
Regel "Alles ist " von C bereits in C ++ 98 gelöscht wurde. Das einzige, was kaputt gehtauto T a
, ist , was sowieso niemand benutzt hat. (Irgendwo in seinen Artikeln über die Geschichte der Sprache kommentiert Stroustrup dies, aber ich kann momentan keine genaue Referenz finden.)(*) Die Behandlung von
int
Zeichenfolgen in B war interessant: Sie würden Arrays verwenden und mehrere Zeichen in jedes Mitglied packen. B war tatsächlich BCPL mit unterschiedlicher Syntax.quelle
-Werror
.Dies ist sowohl eine Antwort als auch ein erweiterter Kommentar zu Nein, dies ist seit 1999 kein legales C mehr. Kein anständiger moderner C-Compiler erlaubt dies.
Ja,
auto a=1;
ist in C1999 (und auch in C2011) illegal. Nur weil dies jetzt illegal ist, bedeutet dies nicht, dass ein moderner C-Compiler Code ablehnen sollte, der solche Konstrukte enthält. Ich würde genau das Gegenteil argumentieren, dass ein anständiger moderner C-Compiler dies noch berücksichtigen muss.Sowohl clang als auch gcc tun genau das, wenn sie den Beispielcode in der Frage mit den Versionen des Standards von 1999 oder 2011 kompilieren. Beide Compiler geben eine Diagnose aus und fahren dann fort, als ob die anstößige Aussage gewesen wäre
auto int a=1;
.Meiner Meinung nach sollte ein anständiger Compiler dies tun. Durch die Ausgabe einer Diagnose entsprechen clang und gcc vollständig dem Standard. Der Standard besagt nicht, dass ein Compiler illegalen Code ablehnen muss. Der Standard besagt lediglich, dass eine konforme Implementierung mindestens eine Diagnosemeldung erzeugen muss, wenn eine Übersetzungseinheit eine Verletzung einer Syntaxregel oder -beschränkung enthält (5.1.1.3).
Bei Code, der unzulässige Konstrukte enthält, versucht jeder anständige Compiler, den unzulässigen Code zu verstehen, damit der Compiler den nächsten Fehler im Code finden kann. Ein Compiler, der beim ersten Fehler stoppt, ist kein sehr guter Compiler. Es gibt eine Möglichkeit, einen Sinn daraus zu machen
auto a=1
, nämlich die "implizite int" -Regel anzuwenden. Diese Regel zwingt den Compiler, so zu interpretieren,auto a=1
als obauto int a=1
der Compiler im C90- oder K & R-Modus verwendet würde.Die meisten Compiler lehnen normalerweise Code ab (ablehnen: Verweigern der Generierung einer Objektdatei oder einer ausführbaren Datei), der eine unzulässige Syntax enthält. Dies ist ein Fall, in dem die Compilerautoren entschieden haben, dass ein fehlgeschlagenes Kompilieren nicht die beste Option ist. Am besten stellen Sie eine Diagnose, korrigieren den Code und fahren fort. Es gibt einfach zu viel Legacy-Code, der mit Konstrukten wie gespickt ist
register a=1;
. Der Compiler sollte in der Lage sein, diesen Code im C99- oder C11-Modus zu kompilieren (natürlich mit einer Diagnose).quelle
-ffs-please-stop-allowing-constructs-from-some-previous-millennium
Compiler-Option oder genauer gesagt eine-fstrict-compliance
Option. Murren über den Compiler: "Als ich -std = c11 verwendete, hatte ich nicht erwartet, dass dieser alte K & R-Kruft kompiliert wird. Eigentlich wollte ich, dass er nicht kompiliert wird!"-std=c99
strenger zu sein wäre ein Schritt in die richtige Richtung :)gcc -g -O3 -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror
(was ich routinemäßig verwende, auch bei Code aus Fragen zu SO), kommen Sie dem, was Sie wollen, ziemlich nahe. Ich möchte, dass GCC mindestens-std=c99
und vorzugsweise standardmäßig verwendet wird-std=c11
(oder, das-std=gnu11
würden sie eher tun), aber bis dahin… können Sie diese Optionen optimieren.-pedantic
,-Wshadow
,-Wold-style-declaration
Und einige andere können nützlich sein, aber das ist eine gute Optionen zu starten.-pedantic-errors
auto
hat eine Bedeutung inC
undC++
vor dem Standard 2011. Dies bedeutet, dass eine Variable eine automatische Lebensdauer hat, dh eine Lebensdauer, die vom Bereich bestimmt wird . Dies steht beispielsweise derstatic
Lebensdauer entgegen, bei der eine Variable unabhängig vom Umfang "für immer" gültig ist.auto
ist die Standardlebensdauer und wird fast nie explizit angegeben. Deshalb war es sicher, die Bedeutung in zu ändernC++
.Jetzt in
C
vor dem 99 - Standard, wenn Sie nicht den Typ einer Variablen angeben, wird standardmäßigint
.Also mit
auto a = 1;
Ihnen (und definieren) eine deklarierenint
Variable, mit Lebensdauer durch den Umfang bestimmt.("Lebensdauer" wird besser als "Speicherdauer" bezeichnet, aber ich denke, das ist vielleicht weniger klar).
quelle
main
Funktionsumfangs".auto
undstatic
sind die einzigen beiden Möglichkeiten. Ich habe versucht, meine Antwort so zu schreiben, dass sie sich an den Fragesteller richtet, der fürC++
(undC
) ziemlich neu zu sein scheint , also habe ich die Details ein wenig beschönigt. Vielleicht war das eine schlechte Idee; Sie müssen früher oder später abgedeckt werden.int
Zeug wird seit 1999 aus C entfernt.In C und in historischen Dialekten von C ++
auto
ist dies ein Schlüsselwort,a
das automatisch gespeichert wird. Da es nur auf lokale Variablen angewendet werden kann, die standardmäßig automatisch sind, wird es von niemandem verwendet. Aus diesem Grund hat C ++ das Schlüsselwort jetzt neu verwendet.In der Vergangenheit hat C Variablendeklarationen ohne Typspezifizierer zugelassen. Der Typ ist standardmäßig
int
. Diese Erklärung entspricht alsoIch denke, dass dies im modernen C veraltet (und möglicherweise verboten) ist; Einige beliebte Compiler verwenden jedoch standardmäßig C90 (was meiner Meinung nach dies zulässt) und aktivieren Warnungen ärgerlicherweise nur, wenn Sie ausdrücklich danach fragen. Das Kompilieren mit GCC und das Angeben von C99 mit
-std=c99
oder das Aktivieren der Warnung mit-Wall
oder-Wimplicit-int
gibt eine Warnung aus:quelle
In C
auto
bedeutet dies dasselberegister
wie in C ++ 11: Es bedeutet, dass eine Variable eine automatische Speicherdauer hat.Und in C vor C99 (und der Compiler von Microsoft unterstützt weder C99 noch C11, obwohl er möglicherweise Teile davon unterstützt) kann der Typ in vielen Fällen weggelassen werden, wo er standardmäßig verwendet wird
int
.Der Typ wird vom Initialisierer überhaupt nicht übernommen. Sie haben gerade einen kompatiblen Initialisierer ausgewählt.
quelle
auto
undregister
hatte genau die gleiche Bedeutung (ich habe zuvor kommentiert, dass es Einschränkungenregister
gab, die Adresse einer qualifizierten Variablen zu verwenden, aber das war für C ++ falsch).register
, obwohl veraltet, behält seine alte Bedeutung für jetzt.auto
in C dasselbe bedeutet wieregister
in C ++, was es tut (beide bedeuten automatische Speicherdauer und sonst nichts).Der Visual Studio-Kompilierungstyp ist unter verfügbar
right click on file -> Properties -> C/C++ -> Advanced -> Compile As
. Um sicherzustellen, dass es als C-Force-/TC
Option kompiliert wird. In diesem Fall ist es das, was Larsmans gesagt haben (altes C-auto
Schlüsselwort). Es kann ohne Ihr Wissen als C ++ kompiliert werden.quelle
Eine Speicherklasse definiert den Umfang (Sichtbarkeit) und die Lebensdauer von Variablen und / oder Funktionen innerhalb eines C-Programms.
Es gibt folgende Speicherklassen, die in einem C-Programm verwendet werden können
auto
ist die Standardspeicherklasse für alle lokalen Variablen.Das obige Beispiel definiert zwei Variablen mit derselben Speicherklasse. auto kann nur innerhalb von Funktionen verwendet werden, dh innerhalb lokaler Variablen.
int
ist der Standardtyp für denauto
folgenden Code:Der folgende Code ist ebenfalls legal:
quelle