“Wenn die Größe des Arrays bekannt ist, kann sie um eins kleiner sein als die Größe des Zeichenfolgenliterals. In diesem Fall wird das abschließende Nullzeichen ignoriert.”
Wenn ich jedoch denselben Code in C++ erstellen würde, erhalte ich den folgenden C++-Fehler:
error: initializer-string for array of chars is too long
[-fpermissive] char str[3]="abc";
Ich hoffe jemand kann das erläutern.
Fragen:
Ist das Codebeispiel in allen C-Sprachstandards gültig?
Ist es in allen C++-Sprachstandards ungültig?
Gibt es einen Grund, der in einer Sprache gültig ist, aber nicht in einer anderen?
Sie zitieren alle Normen selbst. Ja, es ist gültiges C. Ja, es ist falsch formatiertes C++. Was ist unklar? Und nein, niemand kennt den Grund genau, aber Konsens besteht darin, dass C++ strenger ist als C im Allgemeinen.
– SergejA
16. Juni 2016 um 14:09 Uhr
C und C++ sind unterschiedliche Sprachen. Warum erwarten Sie also, dass sie sich identisch verhalten? Und C-Code nur in C++ zum Laufen zu bringen, ist im Allgemeinen eine schlechte Idee. Verwenden Sie den C-Code entweder weiterhin als separates Modul oder schreiben Sie ihn mithilfe der C++-Funktionen/-Bibliothek ordnungsgemäß neu. Und der gezeigte Code ist auch in C schlecht – es sei denn, Sie wollen keinen “String”. In diesem Fall ist die Verwendung einer Initialisiererliste sowieso der bessere Ansatz.
– zu ehrlich für diese Seite
16. Juni 2016 um 14:10 Uhr
@Olaf GNU89 ist auch ein Standard.
– fuz
16. Juni 2016 um 14:14 Uhr
Lassen Sie uns Kommentare höflich halten und Beleidigungen vermeiden. Ich habe hier aufgeräumt.
– Brad Larson ♦
16. Juni 2016 um 14:23 Uhr
@Olaf “Warum erwartest du, dass sie sich identisch verhalten?” Weil C++ auf Kompatibilität ausgelegt ist und die Standardkomitees versuchen, es zu bewahren, wenn dies möglich und angemessen ist. Beispielsweise ist die C-Standardbibliothek Teil des C++-Standards; die meisten Implementierungen verwenden dieselben Bibliotheksbinärdateien und Header-Quellen für beide Sprachen. Dass das möglich ist, ist ein Designmerkmal. Abweichungen von dieser Faustregel sind selten und werden von den Ausschussmitgliedern oft im Nachhinein bedauert.
– Peter – Setzen Sie Monica wieder ein
16. Juni 2016 um 16:52 Uhr
NathanOliver
Was Sie hier sehen, ist ein Unterschied in den Initialisierungsregeln für cstring in C und C++. In C11 §6.7.9/14 haben wir
Ein Array vom Zeichentyp kann durch ein Zeichenfolgenliteral oder ein UTF-8-Zeichenfolgenliteral initialisiert werden, optional eingeschlossen in geschweiften Klammern. Aufeinanderfolgende Bytes des Zeichenfolgenliterals (einschließlich des abschließenden Nullzeichens, falls Platz vorhanden ist oder wenn das Array eine unbekannte Größe hat) die Elemente des Arrays initialisieren.
Betonung von mir
Solange das Array also groß genug für die Zeichenfolge ohne das Null-Terminator ist, ist es gültig. So
char str[3]="abc";
Gültig ist C. In C++14 hingegen findet sich die Regel, die dies regelt in [dcl.init.string]/2 Staaten
Es darf nicht mehr Initialisierer als Array-Elemente geben.
Und zeigt weiter, dass der folgende Code ein Fehler ist
char cv[4] = "asdf"; // error
In C++ müssen Sie also genügend Speicherplatz für das gesamte Zeichenfolgenliteral einschließlich des Nullterminators haben.
Es könnte eine gute Idee sein, anzugeben, welche Standards Sie zitieren.
– fuz
16. Juni 2016 um 14:26 Uhr
@FUZxxl Habe ich gerade gemacht. Ich zitiere die aktuellen Standards.
– NathanOliver
16. Juni 2016 um 14:27 Uhr
Es könnte nützlich sein, einen Blick auf die C++-Entwurfslogik zu werfen, aber ich weiß nicht, wo ich sie finden kann.
– fuz
16. Juni 2016 um 14:35 Uhr
@FUZxxl Höchstwahrscheinlich war es aus Sicherheitsgründen. Normalerweise möchten Sie das Null-Terminator haben, um es zu einem richtigen Cstring zu machen.
– NathanOliver
16. Juni 2016 um 14:36 Uhr
Ich denke, C++ möchte, dass Sie Strings als Strings behandeln, während C immer flexibler war.
– Benutzer5940189
16. Juni 2016 um 15:17 Uhr
Johannes Bode
Ist das Codebeispiel in allen C-Sprachstandards gültig?
Beachten Sie, dass jeweils nur eine ISO-Norm in Kraft ist; C2011 ersetzt C99, das C89 ersetzte.
Ich glaube jedoch, dass es unter jedem dieser Standards gültig sein sollte.
Ist es in allen C++-Sprachstandards ungültig?
Wie oben, ändern Sie einfach “gültig” in “ungültig”.
Gibt es einen Grund, der in einer Sprache gültig ist, aber nicht in einer anderen?
Höchstwahrscheinlich wurde es in C gültig gelassen, um keinen Legacy-Code zu beschädigen, der sich auf das Verhalten stützte. C++ kam ungefähr ein Jahrzehnt nach C und versuchte, einige der Mängel von C zu beheben, und dies war eine der Lücken, die gestopft wurden.
Viele moderne Programmiersprachen sind Iterationen und Verbesserungen früherer Sprachen; C ist B mit einem Typsystem, C++ ist C mit OO-Unterstützung und besserer Typsicherheit, Java und C# sind C++ mit weniger undefiniertem Verhalten usw.
Java hat fast nichts mit C++ gemeinsam. Geschweifte Klammern sind ihr wichtigstes gemeinsames Merkmal.
– n. 1.8e9-wo-ist-meine-Aktie m.
16. Juni 2016 um 15:45 Uhr
Wenn eine Struktur Platz für eine Zeichenfolge mit exakter Größe enthält, ist es viel bequemer, das Element als “INIT” initialisieren zu lassen, als es als {‘I’,’N’,’I’,’T’ schreiben zu müssen. }. Am besten wäre es gewesen, eine Syntax zu haben, um explizit eine Zeichenfolge ohne Abschlusszeichen anzugeben, aber weder C noch C++ scheinen das zu haben.
– Superkatze
16. Juni 2016 um 16:56 Uhr
@nm Alles an ihrer Syntax ist buchstäblich identisch, aber es hört dort auf.
– Katze
16. Juni 2016 um 21:17 Uhr
12346000cookie-checkWelche Sprachstandards erlauben das Ignorieren von Nullterminatoren bei Arrays mit fester Größe?yes
Sie zitieren alle Normen selbst. Ja, es ist gültiges C. Ja, es ist falsch formatiertes C++. Was ist unklar? Und nein, niemand kennt den Grund genau, aber Konsens besteht darin, dass C++ strenger ist als C im Allgemeinen.
– SergejA
16. Juni 2016 um 14:09 Uhr
C und C++ sind unterschiedliche Sprachen. Warum erwarten Sie also, dass sie sich identisch verhalten? Und C-Code nur in C++ zum Laufen zu bringen, ist im Allgemeinen eine schlechte Idee. Verwenden Sie den C-Code entweder weiterhin als separates Modul oder schreiben Sie ihn mithilfe der C++-Funktionen/-Bibliothek ordnungsgemäß neu. Und der gezeigte Code ist auch in C schlecht – es sei denn, Sie wollen keinen “String”. In diesem Fall ist die Verwendung einer Initialisiererliste sowieso der bessere Ansatz.
– zu ehrlich für diese Seite
16. Juni 2016 um 14:10 Uhr
@Olaf GNU89 ist auch ein Standard.
– fuz
16. Juni 2016 um 14:14 Uhr
Lassen Sie uns Kommentare höflich halten und Beleidigungen vermeiden. Ich habe hier aufgeräumt.
– Brad Larson
♦
16. Juni 2016 um 14:23 Uhr
@Olaf “Warum erwartest du, dass sie sich identisch verhalten?” Weil C++ auf Kompatibilität ausgelegt ist und die Standardkomitees versuchen, es zu bewahren, wenn dies möglich und angemessen ist. Beispielsweise ist die C-Standardbibliothek Teil des C++-Standards; die meisten Implementierungen verwenden dieselben Bibliotheksbinärdateien und Header-Quellen für beide Sprachen. Dass das möglich ist, ist ein Designmerkmal. Abweichungen von dieser Faustregel sind selten und werden von den Ausschussmitgliedern oft im Nachhinein bedauert.
– Peter – Setzen Sie Monica wieder ein
16. Juni 2016 um 16:52 Uhr