Die Zeile mit der Incrementierung liefert folgenden Compilerfehler:
error: lvalue required as increment operand
Das verstehe ich nicht.
Ich hätte erwartet das ((const long*)mem) vom Typ const long* ist, den
ich mit ++ incrementieren können sollte, oder?
Wenn ich die eine Zeile durch folgenden Codeausschnitt ersetze, gibt es
keine Compilerfehler mehr:
1
constlong*a;
2
a=((constlong*)mem);
3
a++;
4
mem=(void*)a;
Was mache ich falsch? Macht der 3-Zeiler das was ich möchte (auf den
nächsten const long zeigen)?
Schon mal vielen Dank für hilfreiche Hinweise,
Paul Roßmann
ps.: als Compiler verwende ich den arm-none-eabi-gcc 4.7.3 20121207
(release)
Paul Roßmann schrieb:> Das verstehe ich nicht.> Ich hätte erwartet das ((const long*)mem) vom Typ const long* ist,
Ist es auch.
Aber:
Das ist ein Ausdruck. Da entsteht also ein temporäres Zwischenergebnis.
Nämlich ein Pointer der vom Typ const long* ist.
Dein Code versucht jetzt genau dieses temporäre Zwischenergebnis zu
inkrementieren.
Das geht zwar im Prinzip, ist aber sicher nicht das was du willst. Denn
ein temporäres Zwischenergebnis zu inkrementieren, welches nach
Beendigung der kompletten Anweisung (beim nächsten Sequence Point)
wieder ins Nirvana verschwindet, macht in den meisten Fällen keinen
Sinn.
> Wenn ich die eine Zeile durch folgenden Codeausschnitt ersetze, gibt es> keine Compilerfehler mehr:>
1
>constlong*a;
2
>a=((constlong*)mem);
3
>a++;
4
>mem=(void*)a;
5
>
logisch.
Jetzt wird ja auch kein Zwischenergebnis mehr inkrementiert, sondern
eine tatsächlich real existierende Variable.
Dein ursprünglicher Code ist eine Variante von
1
inti=5,j=8;
2
3
(i-j)++;
i - j ist ein arithmetischer Ausdruck, der ein Ergebnis hat. Dieses
Ergebnis kann man nicht inkrementieren. Es existiert ja nicht real im
Speicher.
In diesem Sinne ist auch der Cast nichts anderes als diese Subtraktion
hier: Ein Operator, der ein Argument nimmt und daraus ein Ergebnis
erzeugt. Bei einem Cast bleibt (in diesem Fall) dann zwar der Zahlenwert
konstant, aber der Datentyp ändert sich. Aber es ist trotzdem ein
Operator, der aus einem Argument ein Ergebnis macht. Und dieses Ergebnis
ist temporär.
Paul Roßmann schrieb:> error: lvalue required as increment operand>> Das verstehe ich nicht.> Ich hätte erwartet das ((const long*)mem) vom Typ const long* ist, den> ich mit ++ incrementieren können sollte, oder?
Ersteres ist richtig. Aber das Ergebnis eines Casts ist eben kein
lvalue. Ändern kann man aber nur lvalues. Wie sollte es auch anders
gehen? Hier wird der Wert aus mem gelesen und dieser dann in einen const
long* konvertiert. Es wäre jetzt wenig sinnvoll, diesen temporären Wert
zu erhöhen, weil er nach der Zeile sowieso aufhört zu existieren. Auf
mem hätte es so oder so keinen Einfluss.
> Wenn ich die eine Zeile durch folgenden Codeausschnitt ersetze, gibt es> keine Compilerfehler mehr: const long *a;> a = ((const long*)mem);> a++;> mem = (void*)a;>> Was mache ich falsch?
Hier versuchst du nicht, das Ergebnis des Casts zu inkrementieren,
sondern stattdessen, es in eine Variable zu schreiben und dann diese zu
inkrementieren. Das geht.
Paul Roßmann schrieb:> Um mir den 3-Zeiler und die explizit deklarierte Hilfsvariable zu sparen
Was sich die Leute nicht alles für schräges Zeug ausdenken.
Leut's, Hilfsvariablen kosten nichts. Wenn der Compiler sie
wegoptimieren kann, macht er das ohnehin. Dafür kann man danach
wenigstens auch lesen, was du da eigentlich anstellen wolltest.
Jörg Wunsch schrieb:> Was sich die Leute nicht alles für schräges Zeug ausdenken.>> Leut's, Hilfsvariablen kosten nichts. Wenn der Compiler sie> wegoptimieren kann, macht er das ohnehin. Dafür kann man danach> wenigstens auch lesen, was du da eigentlich anstellen wolltest.
Volle Zustimmung.
Wieso glauben so viele Leute fälschlicherweise, dass Code besser würde,
wenn man so viel wie möglich davon in eine Zeile packt? :-(
Mark Brandis schrieb:> Wieso glauben so viele Leute fälschlicherweise, dass Code besser würde,> wenn man so viel wie möglich davon in eine Zeile packt? :-(
Weil der C Compiler 1 Zeile pro Microsekunde ausführt ;-)
Tatsächlich ist mir bewusst das
a) der Compiler optimiert was er kann
b) Lesbarkeit wichtig ist
c) man hier (im Forum) schnell und gut geholfen wird
d) man schreiben würde was geschrieben wurde
Ich hatte überlegt (nachdem der Einzeiler dann da stand) wieder die
längere Variante zu nehmen, mich aber dagegen entscheiden, weil ich
weder die eine noch die andere Variante besser lesbar finde.
Was mich noch interessieren würde ist ob auch
1
mem+=sizeof(long)
funktionieren würde. Das fände ich tatsächlich gut lesbar, einfach,
kurz. Nur habe ich den Verdacht das das nicht immer funktioniert.
Viele Grüße
Paul Roßmann
Ohne Testen würde ich sagen: klappt nicht.
Angenommen, sizeof(long) liefert 4.
Dann würde der Zeiger um 4 * sizeof(Zeigertyp) erhöht werden. mem zeigt
aber auf void.
Was ist sizeof(void)?
lässt mich annehmen, dass der Pointer innerhalb der Funktion nicht nur
dazu dient um erhöht zu werden.
D.h. es wird sowieso sinnvoll sein, den void Pointer sofort auf einen
lokalen uint8_t Pointer umzukopieren um die Funktion von Casts zu
befreien.