Was ist der Zweck des unären Plus (+) - Operators in C?

78

In C ist es legal, etwas zu schreiben wie:

Soweit ich das beurteilen kann, ist das unäre Plus ( +) in +4jedoch ein No-Op. Ist es?

zneak
quelle
Nicht genau das gleiche, aber verwandt: stackoverflow.com/questions/727516/…
jglouie
5
msdn.microsoft.com/en-us/library/s50et82s.aspx "Der unäre Plus-Operator vor einem Ausdruck in Klammern erzwingt die Gruppierung der eingeschlossenen Operationen. Er wird mit Ausdrücken verwendet, an denen mehr als ein assoziativer oder kommutativer binärer Operator beteiligt ist. Der Operand muss einen arithmetischen Typ haben. Das Ergebnis ist der Wert des Operanden. Ein integraler Operand wird einer integralen Heraufstufung unterzogen. Der Typ des Ergebnisses ist der Typ des heraufgestuften Operanden. "
Tim S.
6
K & R sagt, es wurde nur aus Symmetriegründen in den Standard aufgenommen.
Aaron Yodaiken
2
@ Jeremy: gibt es. ZB heißt es, dass +short(1)Typ hat int, nicht short.
MSalters
1
@TimS.: " Der unäre Plus-Operator vor einem Ausdruck in Klammern erzwingt die Gruppierung der eingeschlossenen Operationen " - Oh? Es sind die Klammern, nicht die +, die die Gruppierung erzwingen.
Keith Thompson

Antworten:

34

Gemäß C90-Standard in 6.3.3.3:

Das Ergebnis des Operators unary + ist der Wert seines Operanden . Die integrale Promotion wird für den Operanden durchgeführt. und das Ergebnis hat den heraufgestuften Typ.

und

Der Operand des unären Operators + oder - muss einen arithmetischen Typ haben .

lccarrasco
quelle
1
Also +xist ein Noop es sei denn sizeof x < sizeof(int)?
Zneak
31
Diese Zitate aus dem Standard zeigen, dass das unäre + nicht einfach ein No-Op ist. Es führt eine integrale Promotion für den Operanden durch. Und, was vielleicht noch wichtiger ist, es verwandelt einen l-Wert in einen r-Wert.
Sander De Dycker
Nun, es ist theoretisch möglich, dass sizeof(short) == sizeof(int)aber a shorteine Polsterung hat, und theoretisch muss bei einem solchen System die Polsterung auf Null gesetzt oder das Vorzeichen erweitert werden. Theoretisch.
Dietrich Epp
Beachten Sie, dass sich das Beispiel Nemo auf Werke bezieht, wenn der arithmetische Typ sowohl auf integrale als auch auf schwebende Typen verweist, da Zeiger außerhalb dieser Klassifizierung liegen. Integrale Typen und Zeiger bilden Skalartypen.
lccarrasco
Dies wirkt sich nicht auf a floatoder a aus, oder double?
SS Anne
77

Sie können es als eine Art Behauptung verwenden, dass ein Ausdruck einen arithmetischen Typ hat:

Dies erzeugt einen Fehler bei der Kompilierung, wenn xein Zeiger ausgewertet wird.

Das ist ungefähr der einzige praktische Nutzen, den ich mir vorstellen kann.

Nemo
quelle
7
Auf diese Weise können Sie auch einen Aufzählungswert in seinen ganzzahligen Wert umwandeln.
GManNickG
2
Warum können Sie zum Beispiel nicht dasselbe tun (-(-(x)))?
Aaron Yodaiken
8
@luxun @zneak: Interessante Idee ... Lass mich sehen ... OK, wie wäre es damit. Wenn intes 32-Bit ist und xzufällig intgleich ist -2^31, -xwird eine vorzeichenbehaftete Ganzzahl überlaufen, die technisch undefiniertes Verhalten ist. :-)
Nemo
4
@zneak: Der Punkt ist, einen Kompilierungszeitfehler auszulösen, wenn der Ausdruck einen Zeigertyp hat, aber ein No-Op zu sein, wenn er einen arithmetischen Typ hat. Ihre Version funktioniert einwandfrei, mit Ausnahme von arithmetischen Ausdrücken, die zufällig ausgewertet werden INT_MIN. (Nun, theoretisch jedenfalls. In der Praxis funktioniert es wahrscheinlich auf jeder realistischen Maschine einwandfrei.) Eine strenge Lesart des Standards besagt jedoch, dass diese unterschiedlich sind.
Nemo
1
@zneak: Auch wenn Sie es nicht in einer Zuweisung verwenden, nur zu bewerten , -xwenn xist INT_MINtechnisch nicht definiertes Verhalten zu berufen ist, glaube ich.
Nemo
35

Es gibt eine sehr praktische Verwendung des mir bekannten unären Plus-Operators: in Makros. Angenommen, Sie möchten so etwas tun

Wenn dies nicht FOOdefiniert ist, muss es in der C-Sprache in diesem Fall durch 0 ersetzt werden. Wenn dies FOOjedoch mit einer leeren Definition definiert wurde, führt die obige Anweisung zu einem Fehler. Stattdessen können Sie verwenden:

Und jetzt ist die Direktive syntaktisch korrekt, unabhängig davon FOO, ob sie undefiniert, als leer oder als ganzzahliger Wert definiert ist.

Ob dies die gewünschte Semantik ergibt, ist natürlich eine völlig separate Frage, aber in einigen nützlichen Fällen wird dies der Fall sein.

Bearbeiten: Beachten Sie, dass Sie dies sogar verwenden können, um die Fälle der FOODefinition als Null gegenüber der Definition als leer zu unterscheiden, wie in:

R .. GitHub HÖREN SIE AUF, EIS ZU HELFEN
quelle
1
Sind Sie sicher, dass sich diese Präprozessor-Direktiven wirklich auf den unären Operator + beziehen, wie in C zu sehen? In FOO
Ihrem
2
In der Tat. In jedem Fall entspricht das Operatorenpaar - -(Platzbedarf!) +Soweit ich das +beurteilen kann, was ziemlich redundant ist ... Nein, das ist falsch, es ist nicht äquivalent, wenn der Operand INT_MIN... :-)
R. GitHub STOP HELPING ICE
2
Tut mir leid, dass ich so eine alte Antwort gestoßen habe, aber ist dies nicht eher ein Beispiel für das binäre Plus als für das unäre Plus?
Aurora Vollvik
2
@ AuroraVollvik: Es ist unary Plus, wenn das Makro zufällig definiert ist, aber eine leere Definition hat.
R .. GitHub STOP HELPING ICE
2
@UndefinedBehavior: Ob es unär oder binär ist, hängt davon ab, wie FOOes definiert ist.
R .. GitHub STOP HELPING ICE
17

Ja schon. Es dient hauptsächlich der Vollständigkeit und um Konstruktionen wie diese ein wenig sauberer aussehen zu lassen:

Dämmerung -inaktiv-
quelle
2
Auf keinen Fall ist dies sauberer als die Alternative ohne die unären +s.
Ruohola
14

Nicht gerade ein No-Op

Der unäre +Operator macht nur eines: Er wendet die ganzzahligen Beförderungen an . Da diese ohnehin auftreten würden, wenn der Operand in einem Ausdruck verwendet würde, stellt man sich vor, dass unary +in C ist, nur um die Symmetrie mit unary zu gewährleisten -.

Es ist schwierig, dies in Aktion zu sehen, da die Werbeaktionen so allgemein angewendet werden.

Ich habe mir das ausgedacht:

welche (auf meinem Mac) druckt

DigitalRoss
quelle
1
Dies ist nützlich zum Drucken von chars in C ++ mit std::cout.
SS Anne
13

Was ist der Zweck des unären '+' - Operators in C?

Unäres Plus wurde zu C hinzugefügt, um die Symmetrie mit unärem Minus zu gewährleisten. C :

Unary Plus wurde vom C89-Komitee aus mehreren Implementierungen zur Symmetrie mit Unary Minus übernommen.

und es ist kein No-Op, es führt die ganzzahligen Heraufstufungen für seinen Operanden durch. Zitat aus meiner Antwort auf Führt der Unary + -Operator Typkonvertierungen durch? ::

Der Entwurf des C99-Standardabschnitts 6.5.3.3 Unäre arithmetische Operatoren lautet:

Das Ergebnis des Operators unary + ist der Wert seines (heraufgestuften) Operanden. Die ganzzahligen Heraufstufungen werden für den Operanden ausgeführt , und das Ergebnis hat den heraufgestuften Typ.

Es sei darauf hingewiesen, dass das Annotated C ++ Reference Manual ( ARM ) den folgenden Kommentar zu unary plus enthält:

Unary Plus ist ein historischer Unfall und im Allgemeinen nutzlos.

Shafik Yaghmour
quelle
In C ++ wird es auch "missbraucht", wenn a static_castdie Absicht deutlicher zeigen würde, zum Beispiel das Auflösen einer mehrdeutigen Überlastung des Funktionszeigers und der std :: -Funktion für ein Lambda mit +
Shafik Yaghmour
13

Ich habe zwei Dinge gefunden, die ein unärer +Operator tut

  • integer promotion
  • turning lvalue into rvalue

Beispiel für eine Ganzzahl-Promotion:

Typische Ausgabe (auf 64-Bit-Plattform):

lvalue in rvalue verwandeln Beispiel:

Als Bhullar
quelle
1
Schließlich. Eine potenziell nützliche Anwendung, die einen generischen Code über die Größe eines Arguments nach einer Ganzzahl-Heraufstufung informiert, die möglicherweise nicht vorhanden ist sizeof(int). Ich habe keine Ahnung, wann ich es verwenden werde. Aber trotzdem schön. NB: Antwort bearbeitet, um zu zeigen, dass nicht alles bis 4.
Persixty
1

Mit "no-op" meinen Sie die Montageanleitung?
Wenn ja, dann definitiv nicht.

+4 ist nur 4 - der Compiler fügt keine weiteren Anweisungen hinzu.

DefenestrationDay
quelle
2
Mit 'noop' meinte ich 'nichts tun' - ich erwarte, dass Compiler keine Anweisung hinzufügen, um eine Anweisung hinzuzufügen.
Zneak
3
Ist +(char)4aber nicht dasselbe wie (char)4.
DigitalRoss