[C]lvalue required bei Präinkrement

Herakles

Profifragensteller
Moin!

Kurz und knapp: Warum geht das hier nicht?

Code:
int main(void){
    int i;

   ++i %= 5;
   return 0;
}

Compiler meldet, dass er eine "lvalue" erwartet, sie aber nicht bekommt.

Wo ist dieser Code unlogisch und fehlerhaft?

Danke im Voraus sagt der Neugierige
Herakles
 
Ich würde mal tippen, dass der Präinkrement-Operator den um Eins erhöhten Wert von i als Konstante liefert. Und dieser Konstante kannst Du mit %= natürlich keinen neuen Wert zuweisen.

Evtl. mal den Postinkrement-Operator probieren, oder noch besser: Das Ganze in zwei Anweisungen schreiben. Also erst inkrementieren, dann den Divisionsrest zuweisen. Ein weiterer Vorteil ist, dass man dann auch die Woche drauf noch den eigenen Code versteht. ;-) Und Variablen am besten gleich bei der Erzeugung mit einem definierten Wert belegen.
 
Ich glaube das ist egal, denn "++i" steht ja fuer "i = i + 1", wobei bei "++i" "i" zurueckgegeben wird und bei "i++" "i + 1", was beides rvalues sind, denen man wie du schon sagtest nichts zuweisen kann.

Vllt warten wir da auch mal auf Tron, der ist doch unser Compiler Experte. ;)
 
++i ist kein L-Value (hat keine Speicheradresse)


und noch eine Kleinigkeit:
i ist nicht initialisiert -> undefiniertes Verhalten Festplatte könnte formatiert werden
 
i ist nicht initialisiert -> undefiniertes Verhalten Festplatte könnte formatiert werden

Das ist so nicht richtig. In einem der C-Standards (ich glaube es ist C99, Tron weiß das sicherlich genauer) ist festgelegt, dass nicht explizit initialisierte Variablen implizit mit 0 initialisiert werden.
 
Egal welchen C-Standard man nimmt. Es ist vollkommen egal was in i steht. In der konkreten Anwendung birgt eine uninitialisierte Variable keine Gefahr.

Ich schreibe in der Regel immer noch ANSI-C und habe keine Ahnung was so in C99 passiert. Ich verwende auch Erweiterungen wie Enums nicht, weil ich Enums ohne Typsicherheit mächtig sinnlos finde.
 
Das ist so nicht richtig. In einem der C-Standards (ich glaube es ist C99, Tron weiß das sicherlich genauer) ist festgelegt, dass nicht explizit initialisierte Variablen implizit mit 0 initialisiert werden.

Wenn sie gloabl sind.

An die "Styleguides" an die ich mich halten muss/will steht: immer initialisieren.
Mir ist es lieber.
Aber das ist sicher auch alles eine Geschmacksfrage.
 
Kurz am Rande zu dem Exkurs in Richtung "nicht initialisiert". Ich hab den Code hier einfach in das Editierfenster geschrieben und dabei habe ich einen Flüchtigkeitsfehler gemacht. Bitte geht davon aus, das im obigen Code

Code:
int i=0;

steht. Ihr Erbsenzähler! ;)

Grüße
Herakles
 
Das hatte ich mir schon gedacht.

Drum auch das mit der Festplatte löschen :)
(der Vergleich ist aber aus einem C++ Buch von Scott Meyers)
 
Naja, kommt halt drauf an, wo man sich befindet. Unter richtigen Betriebssystemen sollte das Rechtemanagement tunlichst verhindern, dass so etwas passiert. Zumindest solange man im Userland ist. Aber unter primitiven Systemen wie DOS ist es durchaus denkbar. Rein theoretisch gesprochen, ich bezweifele, dass ein im undefinierten Bereich arbeitendes Programm wirklich mal eine Festplatte gelöscht hat. :)
 
Back to topic, please!

Ich finde das "andere" Thema zwar auch interessant, aber warum macht ihr dafür nicht fix nen neuen Thread auf? das wäre nett... ;'(

Herakles
 
Jeder Operator in C liefert ein Ergebnis, manche haben auch Nebenwirkungen (Zuweisung: Wert einer Variablen ändern, Funktionsaufruf: quasi beliebiges im Speicher ändern). Dieses Ergebnis ist bis auf wenige Ausnahmen immer ein rvalue. Diese Ausnahmen sind Variablen, unärer *, [], . und -> (und seit C99 auch compound literals). Nur diese Ausdrücke liefern einen lvalue, also etwas, an das zugewiesen werden kann (alle Varianten der Zuweisung) oder von dem die Adresse bestimmt werden darf (unäres &).
Selbst wenn ++i einen lvalue liefern würde, dann wäre das Verhalten von ++i %= 5; undefiniert, da zwischen zwei aufeinanderfolgenden Sequenzpunkten (hier Anfang und Ende der Anweisung) das selbe Objekt mehrfach modifiziert werden würde.

Ich glaube das ist egal, denn "++i" steht ja fuer "i = i + 1", wobei bei "++i" "i" zurueckgegeben wird und bei "i++" "i + 1", was beides rvalues sind, denen man wie du schon sagtest nichts zuweisen kann.
++i heißt nicht umsonst Präinkrement: Erst Variable um eins erhöhen, dann den neuen Wert zurückgeben. i++ erhöht auch den Wert von i um eins, aber liefert den vorherigen Wert von i.
 
Zurück
Oben