gcc Konstante mit Komma-Operator in Ausdruck wird nicht zu letztem Ausdruck ausgewertet

Gast #4805786
Ich frage mich gerade, warum im folgenden Code y = 5 gesetzt wird und 
nicht = 3. Mein Compiler (GCC 4.7.2) sagt das jedenfalls und warnt auch 
nicht.

Einerseits sagt der C11-Standard und das GCC manual, dass float 
Konstanten einen Punkt als Dezimaltrennzeichen haben müssen.
OK. Dann wird das also nicht als float verstanden.

Aber dann ist es der Kommaoperator, der das Integer 3 ergibt (das dann 
in double gecasted wird).

Denn das geht doch über Assignment-Expression -> Primary-E -> Unary-E 
oder wie? Aber wäre syntaktisch hier nicht richtig.

Oder wie jetzt?
1
#include "stdio.h"
2

3
main () {
4
  double y;
5

6
  y= 5,3;
7

8
  printf("y: %.2f\n",y);
9
}
Gast
Hm. OK. Richtig. Das Ganze gibt dann zwar 3, aber zuerst mal x = 5.

Danke.

War zu K&R-Zeiten noch schöner. Da gab es eine ausdrückliche Tabelle mit 
Vorrang und Auswertungsreihenfolge und alle Syntax-Alternativen waren 
gleichberechtigt.

Naja.
Gast
Ernstgemeinte Frage: Warum sollte man so etwas tun wollen?
Wenn ich will das y den Wert 3 bekommt, dann wuerde ich einfach y = 3; 
schreiben, anstatt y = 5,3;...
Aber vielleicht denk ich mir das, in meinem jugendlichen leichtsinn, 
auch nur zu einfach. :)
Gast
Rolf M. schrieb:
> ProfessionalMagnifier schrieb:
>> Hm. OK. Richtig. Das Ganze gibt dann zwar 3, aber zuerst mal x = 5.
>
> Ja. Du müßtest
>
1
> x = (5,3);
2
>
> schreiben, damit das gewünschte herauskommt. Ohne die Klammern ist es
> äquivalent zu
>
1
> (x=5),3;
2
>

Das gewünschte wäre hier der Fliesskommawert 5.3 gewesen, aber dafür 
hätte da ein Punkt stehen müssen und kein Komma.

Ich habe mich nur gewundert, warum da kein Syntax-Fehler aufkommt und 
dachte ursprünglich, dass durch die erste Ziffer syntaktisch klar sein 
hätte müssen, das hier ein Literal folge (n müsse) und nur das. Und das 
wiederum, weil es sinnlos ist, an so einer Stelle den Kommaoperator zu 
verwenden, wenn die 3 dann nirgendwo zugewiesen (oder anderweitig 
verwendet) wird.
Aber die Syntax erlaubt sowas, was eigentlich entweder ausserhalb des 
ganzen Ausdrucks, wieder eine Zuweisung (oder auch einen Kontext als 
Parameter) benötigte oder nach dem Komma, damit es eine reale Wirkung 
hätte. So ist die 3 schlicht Watte; man hätte das Komma und die 3 ebenso 
weglassen können. Der Compiler macht daraus ja auch keinen Code, der 
irgendwas bewirkt.

Vielleicht sehe ich da gerade nicht alle Zusammenhänge, aber das sind so 
meine Gedanken dazu.
Eine Besonderheit von C gegenüber etlichen anderen Sprachen ist, dass 
Zuweisungen syntaktisch keine Statements sind, sondern Rechenausdrücke 
mit einem Ergebnis. Sie also überall stehen können, wo ein 
Rechenausdruck zulässig ist.

Das hat Folgen, manche erwünscht, manche bizarr. Die Variante hier 
gehört zu letzterer Gattung. Ist aber einfach nur ein Nebeneffekt dieser 
grundlegenden Sprachentscheidung.

Dass der Kommaoperator schwächer bindet als die Zuweisung hat einen 
simplen Grund. Weil man dadurch dies schreiben kann:
   for (i = 1, k = n; i < k; ++i, --k)
     ...
Persönliche Seite
A. K. schrieb:
> Eine Besonderheit von C gegenüber etlichen anderen Sprachen ist, dass
> Zuweisungen syntaktisch keine Statements sind, sondern Rechenausdrücke
> mit einem Ergebnis.

Ich würd's eher so ausdrücken: Semantisch sind Zuweisungen "Expressions 
with side effekt" also Ausdrücke mit Nebeneffekt.  a = 5 ist also ein 
Ausdruck mit dem Wert 5, der als Nebeneffekt hat, a auf 5 zu setzen.
ProfessionalMagnifier schrieb:
> und warnt auch
> nicht.

Er warnt doch! Schalt einfach alle Warnungen ein, so wie es sich 
gehört:

1
$ cat test.c 
2
#include "stdio.h"
3

4
int main (void) {
5
  double y;
6
  y= 5,3;
7
  printf("y: %.2f\n",y);
8
}
9

10
$ gcc test.c -Wall -Wextra
11
test.c: In function ‘main’:
12
test.c:5:7: warning: right-hand operand of comma expression has no effect [-Wunused-value]
13
   y= 5,3;
14
       ^

oder wenn Du wirklich nichts einreißen lassen willst dann gehts sogar 
noch ne ecke strenger:

1
$ gcc test.c -Wall -Wextra -Wfatal-errors -Werror
2
test.c: In function ‘main’:
3
test.c:5:7: error: right-hand operand of comma expression has no effect [-Werror=unused-value]
4
   y= 5,3;
5
       ^
6
compilation terminated due to -Wfatal-errors.
7
cc1: all warnings being treated as errors

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.