Deklarationen/Definitionen als Anweisungen in C und C++
Lesezeit: 6 Minuten
Zebrafisch
Ich war verwirrt, als dies nicht in C kompiliert wurde:
int main()
{
for (int i = 0; i < 4; ++i)
int a = 5; // A dependent statement may not be declaration
return 0;
}
Ich bin an C++ gewöhnt, wo dies kompiliert wird. Ich habe eine Weile nur verblüfft gestarrt, bis ich mich an eine Antwort hier auf SO erinnerte, wie in C und C++ verschiedene Dinge als “Anweisungen” betrachtet werden. Dies bezog sich auf eine Switch-Anweisung. Sowohl in C als auch in C++ muss ein “Statement” nach der for-Schleife in Klammern stehen. Dies kann sowohl durch Hinzufügen eines Semikolons als auch durch Erstellen eines { } verschnörkelten Klammerblocks erfolgen.
In C++ “int a = 7;” wird als Deklaration, Definition und Initialisierung betrachtet. In CI wird glauben, dass dies alles auch berücksichtigt wird, in C wird es jedoch nicht als “Aussage” betrachtet.
Könnte jemand genau erklären, warum dies in C keine Aussage ist, während es in C ++ ist? Das verwirrt mein Konzept, was eine Aussage ist, weil eine Sprache sagt, dass es so ist, und eine andere sagt, dass es nicht so ist, also bin ich irgendwie verwirrt.
@NathanOliver Ich habe zum ersten Mal auf meinem Visual Studio 2017 sowohl C- als auch C++-Compiler bemerkt, aber ich weiß, dass dies kein großartiges Beispiel für Konformität ist, also habe ich es auf onlinegdb.com versucht und in beiden kompiliert. Hier ist ein Beispiel: onlinegdb.com/SysJyUGnf Tut mir leid, ich bin mir nicht sicher, ob das GCC verwendet oder was. Aber wenn Sie oben rechts zu C++ wechseln, sehen Sie den Unterschied zwischen den beiden.
– Zebrafisch
16. April 2018 um 16:29 Uhr
Welche Art von Antwort suchen Sie? Eine Erklärung des C++-Komitees darüber, warum sie sich entschieden haben, Dinge anders zu machen als C?
– Melpomen
16. April 2018 um 16:30 Uhr
@melpomene Ich fange an zu verstehen, dass eine Definition in einer Sprache nicht dieselbe in einer anderen Sprache haben muss, deshalb ist es eine andere Sprache. Nur dass ich in C und C++, da sie so ähnlich sind, erwartet habe, dass etwas so Grundlegendes wie eine “Anweisung” ein ähnliches Konzept ist, aber dies ist offensichtlich eine große Ausnahme. Ich habe dies zum ersten Mal in einer ziemlich beliebten Frage zum Überspringen der Initialisierung in C- und C++-Switch-Anweisungen bemerkt.
– Zebrafisch
16. April 2018 um 16:33 Uhr
Es gibt viele “Dialekte” von C. Die frühesten erlauben nicht einmal bereichsbezogene Variablen. Sie müssen alle Variablen vor dem gesamten Code deklarieren. “K&R” C zum Beispiel ist radikal anders. Sie sollten angeben, welche Version von C Sie verwenden. (C99 ist bei modernen Compilern am häufigsten).
– Tiger4Hire
16. April 2018 um 17:46 Uhr
AndyG
C++ erlaubte, dass die “Unteranweisung” einer Iterationsanweisung implizit eine zusammengesetzte Anweisung war ([stmt.iter])
Wenn die Unteranweisung in einer Iterationsanweisung eine einzelne Anweisung und keine zusammengesetzte Anweisung ist, ist sie so, als wäre sie in eine zusammengesetzte Anweisung umgeschrieben worden, die die ursprüngliche Anweisung enthält. Beispiel:
while (--x >= 0)
int i;
kann äquivalent umgeschrieben werden als
while (--x >= 0) {
int i;
}
der C-Standard hat diese Sprache nicht.
Außerdem ist die Definition von a Aussage in C++ geändert, um a einzuschließen Deklarationsanweisungalso selbst wenn die obige Änderung nicht vorgenommen würde, wäre sie immer noch legal.
Der Grund, warum das Hinzufügen von geschweiften Klammern funktioniert, ist, dass Ihre Deklaration jetzt zu a wird Zusammengesetzte Aussage die Deklarationen enthalten können.
Sie dürfen eine haben Kennung in einem Schleifenkörper ohne geschweiften Klammern, also können Sie stattdessen Folgendes tun:
int a = 5;
for (int i = 0; i < 4; ++i)
a;
Aha. Ihr Zitat bezieht sich auf eine Iteration, jedoch int a = 7; still wird nicht als Anweisung in einer switch-Anweisung akzeptiert. Dort heißt es: „Ein Label kann nur Teil einer Aussage sein und eine Deklaration ist keine Aussage“. Scheint nicht nur für Iterationen zu gelten, obwohl ich mich vielleicht missverstehe.
– Zebrafisch
16. April 2018 um 16:40 Uhr
Das Zitat zur Iteration (z. B. for, while) muss auch für case-Labels gelten. In C++ case 1: int a = 7; muss in C++ als zusammengesetzte Anweisung gesehen werden, vermute ich? Während in C es nicht ist.
– Zebrafisch
16. April 2018 um 16:45 Uhr
@Zebrafish: Dies kann hilfreich sein stackoverflow.com/q/92396/27678
Beachten Sie, dass es in C++ Deklarationsanweisungen gibt, die Deklarationen und Anweisungen sind. Ebenso sind einfache Deklarationen Init-Anweisungen. Nicht alle Erklärungen sind jedoch Aussagen. Die Grammatik der Deklarationen enthält Dinge, die nicht in der Liste der Anweisungen stehen:
Die Liste der Deklarationsgrammatiken geht noch einige Seiten weiter.
In C ist eine Anweisung (C11-Standardentwurf)
excerpt from Statements and blocks
statement:
labeled-statement
compound-statement
expression-statement
selection-statement
iteration-statement
jump-statement
Beachten Sie, dass es in C keine Deklarationen gibt, die Anweisungen sind.
Also die Bedeutung von Aussage unterscheidet sich deutlich in den Sprachen. Statement in C++ scheint eine breitere Bedeutung zu haben als Statement in C.
Abhishek Keshri
Gemäß cpReferenz, C++ umfasst folgende Arten von statements:
Ausdrucksanweisungen;
zusammengesetzte Anweisungen;
Auswahlaussagen;
Iterationsanweisungen;
Sprunganweisungen;
Deklarationserklärungen;
Blöcke ausprobieren;
atomare und synchronisierte Blöcke
Während C berücksichtigt folgende Arten von statements:
zusammengesetzte Aussagen
Ausdrucksanweisungen
Auswahl Aussagen
Iterationsanweisungen
Sprunganweisungen
Wie Sie sehen können, werden Deklarationen nicht berücksichtigt statements in C, während dies in C++ nicht der Fall ist.
Für C++:
int main()
{ // start of a compound statement
int n = 1; // declaration statement
n = n + 1; // expression statement
std::cout << "n = " << n << '\n'; // expression statement
return 0; // return statement
} // end of compound statement
Für C:
int main(void)
{ // start of a compound statement
int n = 1; // declaration (not a statement)
n = n+1; // expression statement
printf("n = %d\n", n); // expression statement
return 0; // return statement
} // end of compound statement
Ich sehe user2079303 und Sie haben dieselbe Antwort eingegeben. Dies und das andere erklärt meiner Meinung nach genau, worum es geht. Vielen Dank.
– Zebrafisch
16. April 2018 um 16:51 Uhr
Ich helfe gerne 🙂 Ja, ich habe gepostet und festgestellt, dass er die gleiche Antwort hat, Zeitunterschied weniger als eine Minute, lol;)
– Abhishek Keshri
16. April 2018 um 16:56 Uhr
Aus Gründen der Konsistenz würde ich die zusammengesetzte Anweisung der Funktionsdefinition auch im C++-Beispiel kommentieren.
– Erorika
16. April 2018 um 17:04 Uhr
In C++ sind Deklarationen Anweisungen, während Deklarationen in C keine Anweisungen sind. Also nach der C-Grammatik in dieser for-Schleife
for (int i = 0; i < 4; ++i)
int a = 5;
int a = 5; muss eine Unteranweisung der Schleife sein. Es ist jedoch eine Erklärung.
Sie könnten den Code in C kompilieren, indem Sie beispielsweise die zusammengesetzte Anweisung verwenden
for (int i = 0; i < 4; ++i)
{
int a = 5;
}
obwohl der Compiler eine Diagnosemeldung ausgeben kann, die besagt, dass die Variable a ist nicht benutzt.
Eine weitere Konsequenz, dass Deklarationen in C keine Anweisungen sind. Sie dürfen in C kein Label vor eine Deklaration setzen. Zum Beispiel dieses Programm
#include <stdio.h>
int main(void)
{
int n = 2;
L1:
int x = n;
printf( "x == %d\n", x );
if ( --n ) goto L1;
return 0;
}
kompiliert nicht in C, obwohl es als C++-Programm kompiliert wird. Wenn jedoch eine Null-Anweisung nach dem Label platziert wird, wird das Programm kompiliert.
#include <stdio.h>
int main(void)
{
int n = 2;
L1:;
int x = n;
printf( "x == %d\n", x );
if ( --n ) goto L1;
return 0;
}
14017700cookie-checkDeklarationen/Definitionen als Anweisungen in C und C++yes
@NathanOliver Ich habe zum ersten Mal auf meinem Visual Studio 2017 sowohl C- als auch C++-Compiler bemerkt, aber ich weiß, dass dies kein großartiges Beispiel für Konformität ist, also habe ich es auf onlinegdb.com versucht und in beiden kompiliert. Hier ist ein Beispiel: onlinegdb.com/SysJyUGnf Tut mir leid, ich bin mir nicht sicher, ob das GCC verwendet oder was. Aber wenn Sie oben rechts zu C++ wechseln, sehen Sie den Unterschied zwischen den beiden.
– Zebrafisch
16. April 2018 um 16:29 Uhr
Welche Art von Antwort suchen Sie? Eine Erklärung des C++-Komitees darüber, warum sie sich entschieden haben, Dinge anders zu machen als C?
– Melpomen
16. April 2018 um 16:30 Uhr
@melpomene Ich fange an zu verstehen, dass eine Definition in einer Sprache nicht dieselbe in einer anderen Sprache haben muss, deshalb ist es eine andere Sprache. Nur dass ich in C und C++, da sie so ähnlich sind, erwartet habe, dass etwas so Grundlegendes wie eine “Anweisung” ein ähnliches Konzept ist, aber dies ist offensichtlich eine große Ausnahme. Ich habe dies zum ersten Mal in einer ziemlich beliebten Frage zum Überspringen der Initialisierung in C- und C++-Switch-Anweisungen bemerkt.
– Zebrafisch
16. April 2018 um 16:33 Uhr
Es gibt viele “Dialekte” von C. Die frühesten erlauben nicht einmal bereichsbezogene Variablen. Sie müssen alle Variablen vor dem gesamten Code deklarieren. “K&R” C zum Beispiel ist radikal anders. Sie sollten angeben, welche Version von C Sie verwenden. (C99 ist bei modernen Compilern am häufigsten).
– Tiger4Hire
16. April 2018 um 17:46 Uhr