Frage

In C.1.3 des C ++ IS (2003. Auch im C ++ 11 IS) weist der Standard auf einen Unterschied zwischen ISO C und C ++ hin.nämlich für

char arr[100];

sizeof(0, arr) gibt sizeof(char*) in C zurück, 100 jedoch in C ++.

Ich kann keine Dokumentation für sizeof finden, die zwei Argumente enthält.Der offensichtliche Fallback ist der Komma-Operator, aber ich denke nicht: sizeof(arr) in C ist 100;sizeof(0, arr) ist sizeof(char*).Sowohl sizeof(0, arr) als auch sizeof(arr) sind 100 in C ++.

In diesem Zusammenhang fehlt mir möglicherweise der ganze Sinn des IS.Kann jemand helfen?Dies ähnelt einer Frage, die bereits in '09 diskutiert wurde, aber niemand bezog sich auf den IS, und ich glaube nicht, dass die richtige Antwort gegeben wurde.


Bearbeiten : Tatsächlich spricht der IS über den Kommaoperator.Aus irgendeinem Grund gibt (0, arr) einen char* in C zurück, aber einen char[100] in C ++.Warum?

War es hilfreich?

Lösung

In C zerfällt das Array aufgrund der unterschiedlichen Spezifikation des Kommaoperators in Bezug auf r- und l-Werte in einen Zeiger (nicht der einzige Ort, an dem ein solcher Unterschied gefunden werden kann).In C ++ bleibt das Array ein Array und liefert das richtige Ergebnis.

Andere Tipps

In C erzeugt der Kommaoperator keinen l-Wert, folglich zerfällt der Array-arr, der ein l-Wert ist, in einen Zeigertyp, der ein r-Wert ist (in diesem Fall). sizeof(0,arr) wird also aufgrund der Konvertierung von lWert zu rWert äquivalent zu sizeof(char*).

In C ++ erzeugt der Kommaoperator jedoch einen l-Wert. Es gibt keine Konvertierung von lWert in rWert . Der sizeof(0,arr) bleibt also derselbe, was dem sizeof(char[100]) entspricht.

sizeof ist übrigens keine Funktion, sondern ein Operator. Das Folgende ist also vollständig gültig für C ++ (und C, wenn Sie sich printf anstelle von cout vorstellen):

int a[100], b[200], c[300], d[400];
cout << sizeof(a,b,c,d) << endl;

Demo: http://www.ideone.com/CtEhn

Sie könnten denken, dass ich 4 Operanden an sizeof übergeben habe, aber das ist falsch. sizeof verarbeitet das Ergebnis der Kommaoperatoren. Und es liegt an den vielen Kommaoperatoren, die Sie viele Operanden sehen.

4 Operanden mit 3 Kommaoperatoren; Genau wie bei 1+2+3+4 gibt es 3 Operatoren, 4 Operanden.

Das Obige entspricht dem Folgenden (gültig in C ++ 0x):

auto & result = (a,b,c,d); //first all comma operators operate on the operands.
cout << sizeof (result) << endl; //sizeof operates on the result

Demo: http://www.ideone.com/07VNf

Es ist also der Operator Komma , mit dem Sie das Gefühl haben , dass es viele Argumente gibt. Hier ist Komma ein Operator, aber im Funktionsaufruf ist Komma KEIN Operator, sondern nur ein Argumenttrennzeichen.

function(a,b,c,d); //here comma acts a separator, not operator.

sizeof(a,b,c,d) arbeitet also mit dem Typ des Ergebnisses von ,-Operatoren, genauso wie sizeof(1+2+3+4) mit dem Typ des Ergebnisses von +-Operatoren arbeitet.

Beachten Sie auch, dass Sie keinen sizeof(int, char, short) schreiben können, gerade weil der Operator Komma nicht mit Typen arbeiten kann. Es wird nur mit Wert gearbeitet. Ich denke, sizeof ist der einzige Operator in C und C ++, der auch mit -Typen arbeiten kann. In C ++ gibt es einen weiteren Operator, der Typen bearbeiten kann. Sein Name ist typeid.

Es ist ein Kommaoperator. Und der Unterschied, von dem Sie sprechen, hat absolut nichts mit sizeof zu tun. Der Unterschied liegt wirklich in lWert-zu-r-Wert, Array-zu-Zeiger und ähnlichem Zerfallsverhalten zwischen C- und C ++ - Sprachen. Die

C-Sprache ist in dieser Hinsicht eher triggerfreudig: Arrays zerfallen praktisch sofort in Zeiger (mit Ausnahme sehr weniger spezifischer Kontexte), weshalb das Ergebnis des 0, arr-Ausdrucks den char *-Typ hat. Es entspricht dem 0, (char *) arr.

In C ++ - Spracharrays behalten sie ihre "Arrayness" viel länger bei. Bei Verwendung im Kontext von ,-Operator-Arrays zerfallen Arrays nicht in Zeiger (und l-Werte zerfallen nicht in r-Werte), weshalb in C ++ der Typ des 0, arr-Ausdrucks immer noch char[100] ist.

Dies erklärt den Unterschied im Verhalten von sizeof in diesem Beispiel. Der ?:-Operator ist ein weiteres Beispiel für einen Operator, der den ähnlichen Unterschied im Zerfallsverhalten demonstriert, d. h. der sizeof(0 ? arr : arr) liefert in C und C ++ unterschiedliche Ergebnisse. Grundsätzlich ergibt sich alles aus der Tatsache, dass C-Operatoren normalerweise nicht die Wertigkeit ihrer Operanden bewahren. Viele Operatoren können verwendet werden, um dieses Verhalten zu demonstrieren.

Dies ist kein generischer Codetagcode, der zwei Argumente akzeptiert.sizeof ist ein Operator, keine Funktion.

Beachten Sie, dass sizeof ein Ausdruck ist, der den Kommaoperator verwendet, und alles andere passt.

sizeof akzeptiert keine zwei Argumente. Aber es ist auch keine Funktion, Der (...) begrenzt also keine Funktionsargumente, sondern nur eine optionaler Teil der Syntax und Erzwingen der Gruppierung. Wenn du schreibst sizeof(0, arr), das Argument für sizeof ist der einzelne Ausdruck 0, arr. Ein einzelner Ausdruck mit einem Kommaoperator, der das auswertet Ausdruck links vom Komma, wirft seinen Wert aus (aber nicht seinen Nebenwirkungen), wertet dann den Ausdruck rechts vom Komma aus, und verwendet seinen Wert als Wert des vollständigen Ausdrucks.

Ich bin mir bei C nicht sicher, aber dies könnte ein Unterschied zwischen dem sein Sprachen. In C ++ erfolgt die Konvertierung von Array zu Zeiger nur, wenn dies der Fall ist es wird gebraucht; in C, wenn ich mich richtig erinnere, sagt der Standard, dass es findet immer statt, außer in bestimmten Kontexten. Einschließlich als Betreiber von sizeof. In diesem Fall, da der Komma-Operator dies nicht tut haben Einschränkungen hinsichtlich der Art seiner Operanden, die Die Konvertierung von Array zu Zeiger findet in C ++ nicht statt. In C ein Der Operatand des Komma-Operators ist in den Ausnahmen nicht aufgeführt Die Umwandlung von Array in Zeiger findet statt. (In diesem Fall das Array ist ein Operand des Kommaoperators und nicht des sizeof.)

Der beste Weg, um zu sehen, was hier vor sich gehen könnte, ist die Grammatik im Standard. Wenn wir uns den Entwurf des C99-Standardabschnitts 6.5.3 Unary Operators Absatz 1 ansehen, können wir sehen, dass die Grammatik für sizeof wie folgt lautet:

sizeof unary-expression
sizeof ( type-name )

Der zweite trifft also nicht zu, aber wie gilt der sizeof unary-expression in diesem Fall? Wenn wir uns den Abschnitt A.2.1 Ausdrücke aus dem Standardentwurf ansehen und die Grammatik wie folgt durcharbeiten:

unary-expression -> postfix-expression -> primary-expression -> ( expression )

Wir erhalten die Klammern um einen Ausdruck und müssen uns nun nur noch die Grammatik für Kommaoperator aus dem Abschnitt 6.5.17 Kommaoperator und ansehen wir sehen:

expression:
  assignment-expression
  expression , assignment-expression

Also haben wir jetzt:

sizeof( expression , assignment-expression )
                   ^
                   |
                   comma operator

Sowohl Ausdruck als auch Zuweisungsausdruck können uns zu Primärausdruck führen, der die folgende Grammatik hat:

primary-expression:
  identifier
  constant
  string-literal
  ( expression )

und 0 ist eine Konstante und arr ist eine Kennung , also haben wir:

 sizeof( constant , identifier )

Was macht der Kommaoperator hier? Abschnitt 6.5.17 Absatz 2 sagt:

Der linke Operand eines Kommaoperators wird als ungültiger Ausdruck ausgewertet. da ist ein Sequenzpunkt nach seiner Auswertung. Dann wird der richtige Operand ausgewertet; Das Ergebnis hat seinen Typ und Wert. 97)

Da der Kommaoperator keine der Ausnahmen ist, bei denen ein Array nicht in einen Zeiger konvertiert wird, wird ein Zeiger ausgegeben ( dies wird im Abschnitt 6.3.2.1 behandelt. Werte, Arrays und Funktionsbezeichner ) was bedeutet, dass wir am Ende Folgendes haben:

sizeof( char * )

In C ++ ist die Grammatik ziemlich ähnlich, so dass wir an derselben Stelle enden, aber die Kommaoperatoren funktionieren anders. Der C ++ - Entwurf des Standardabschnitts 5.18 Kommaoperator lautet:

[...] Typ und Wert des Ergebnisses sind Typ und Wert des richtigen Operanden. Das Ergebnis hat dieselbe Wertekategorie wie der richtige Operand [...]

so und Array-zu-Zeiger -Konvertierung ist nicht erforderlich und so erhalten wir:

sizeof( char[100] ) 

Wie bereits mehrere gesagt haben und ich nur eines hinzufügen möchte, ist sizeof ein Operator, der entweder einen Ausdruck oder einen Besetzungsausdruck verwendet. Aus diesem Grund habe ich mir angewöhnt, Paranthesis nur dann auf eine Größe von zu schreiben, wenn es sich um einen gegossenen Ausdruck handelt.

 char *arr;
 struct xxx { ... } v;

Ich werde schreiben

sizeof arr 
sizeof v

aber

sizeof (struct xxx)       /* Note the space after the sizeof, it's important */
sizeof (char *)

Ich mache dasselbe mit return ohne Klammer, da es kein Funktionsaufruf ist, und wenn ich Klammern setze, liegt es daran, dass der folgende Ausdruck sie benötigt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top