Da die Bedingung der while-Schleife immer erfüllt ist (blöde Frage:
wieso ist "1" immer erfüllt?) und keine Anweisungen in der Schleife
vorhanden sind, bleibt das Programm in der Schleife stehen und wartet
--> Endlosschleife. Richtig?
Do Ma schrieb:> blöde Frage: wieso ist "1" immer erfüllt?
Alles ungleich 0 wird von der Schleife als "erfüllt" interpretiert :-)
So, wie du deinen Code geschrieben hast, funktioniert es nicht, da deine
1
while(1)
2
{
3
4
}
wegoptimiert wird...
Probiere doch lieber mal soetwas hier:
Stefan schrieb:> So, wie du deinen Code geschrieben hast, funktioniert es nicht, da deine> while(1)> {>> }> wegoptimiert wird...
nein das passiert nicht, der compiler darf nichts wegoptimiert was das
verhalten ändert.
Peter II schrieb:> nein das passiert nicht, der compiler darf nichts wegoptimiert was das> verhalten ändert.
Und was genau ändert sich am Verhalten, wenn eine sinnlose
while-Schleife wegoptimiert wird???
Schau dir am besten mal das Listing an.
Stefan schrieb:> Und was genau ändert sich am Verhalten, wenn eine sinnlose> while-Schleife wegoptimiert wird???
das der code danach erreicht wird ist schon ein unterschied.
Stefan schrieb:> In diesem Fall trifft Punkt 8 ziemlich genau zu...
Nochmal: Der Compiler darf beim Optimieren nichts weglassen, wenn das
das Verhalten des Programms ändern würde.
Er darf z.B.
while(1); durch einen "HALT"-ASM-Befehl ersetzen, wenn die CPU einen
solchen besitzt.
=> Beides verhindert, dass Code, der nach der Schleife steht, ausgeführt
wird.
Er darf auch allen Quelltext, der in der funktion nach der Schleife
steht, entfernen, "unreachable code".
Aber er darf nicht einfach die Schleife weglassen, und so tun als stände
da nix.
Stefan schrieb:> Eleganter ist es natürlich so:> while(1)> {> asm volatile ("nop");> }
assember in einer Hochsprache zu verwenden ist also Elegant? Was ist
wenn die plattform gar kein nop hat?
Stefan schrieb:> In diesem Fall trifft Punkt 8 ziemlich genau zu...
Na was denn jetzt?
Entweder es trifft zu oder es trifft nicht zu.
"Ziemlich genau" gibt es in der Digitaltechnik und beim Programmieren
nicht.
Und eine Auf-der-Stelle-Trampel-Schleife wird niemals wegoptimiert.
mfg.
Stefan schrieb:> Nenn mir bitte eines...
zeig mir erstmal einen compieler der
while(1) {}
oder
while(1);
wegoptimiert. (gcc macht es zumindest schon mal nicht)
Stefan schrieb:> Spätestens jetzt sollte dann die Sonne aufgehen
Hoffe ich. Spätestens wenn du feststellst, dass in C diese drei
Konstrukte komplett identisch sind:
1
while(1);
2
while(1){}
3
while(1){;}
und zusätzliche Leerzeichen, Einrückungen, Zeilenumbrüche ändern auch
nichts daran.
Alle drei macht der Compiler zu:
Thomas Eckmann schrieb:> Stefan schrieb:>> In diesem Fall trifft Punkt 8 ziemlich genau zu...> Na was denn jetzt?> Entweder es trifft zu oder es trifft nicht zu.> "Ziemlich genau" gibt es in der Digitaltechnik und beim Programmieren> nicht.
@Thomas Eckmann:
Gaaaaaanz ruhig. Nur für dich kann ich es gerne umformulieren: Punkt 8
trifft zu.
> Und eine Auf-der-Stelle-Trampel-Schleife wird niemals wegoptimiert.
Dann lese den Code NOCHMAL (und diesmal aufmerksam) durch. Das ist KEINE
Auf-der-Stelle-Trampel-Schleife sondern ein
Schleife-mit-total-leerem-Rumpf.
Thomas Eckmann schrieb:> Kein C-Compiler macht das. Weil es sonst kein C-Compiler wäre.
Selbst gcc macht das, und das auch noch zurecht :-) Gerne kann ich eine
kleine Wette vorschlagen: Ich bringe Euch den Beweis, und jeder der hier
dumm ohne Ahnung rumheult zahlt mir meinen Stundensatz......
@Stefan
dann zeige uns in beispiel, ich habe es selber getestet und habe es
nicht hinbekommen das er es wegoptimiert. Und wenn hier alle Personen
einer anderen Meinung sind dann würde ich schon mal fragen warum?
Für so ein beispiel braucht du bestimmt keine 2minuten - bei 100€/h sind
das knapp 4€. Dann legen wir mal alle zusammen.
Sorry Namensvetter, aber du schteibst echt Unsinn. Insbesondere
existiert der Unterschied, den du da zu konstruieren versuchst, gar
nicht. Deine beiden while Varianten oben sind absolut identisch.
Εrnst B✶ schrieb:> Wo ist das printf? Und überweist du mir jetzt meinen Stundensatz?
lol
Thema verfehlt, setzen 6
es geht doch darum das das kein Compiler der Welt weg optimiert!
Εrnst B✶ schrieb:> .L2:> jmp .L2
Manfred John schrieb:> es geht doch darum das das kein Compiler der Welt weg optimiert!
Genau das habe ich doch gezeigt. Der Compiler hat die While-Schleife
drinnen gelassen, und stattdessen das Printf wegoptimiert.
Stefan behauptet/wettet, dass der Compiler das while weglässt, und
stattdessen das printf ausführt. Das habe ich widerlegt.
Stefan schrieb:> Gaaaaaanz ruhig. Nur für dich kann ich es gerne umformulieren: Punkt 8> trifft zu
Jetzt halt' dich mal ein bischen zurück.
Stefan schrieb:> Selbst gcc macht das, und das auch noch zurecht :-) Gerne kann ich eine> kleine Wette vorschlagen: Ich bringe Euch den Beweis, und jeder der hier> dumm ohne Ahnung rumheult zahlt mir meinen Stundensatz......
Angenommen. Wo soll ich meine Rechnung hinschicken?
void Inititialize(void)
{
...
while(1);
}
...
170: ff cf rjmp .-2 ; 0x170 <Initialize+0x64>
Und dann erklärst du mal, wie man ein rein interruptgesteuertes Programm
aufbaut, einen Watchdog-Reset erzwingt oder wie man einen Controller in
einem definierten Zustand anhält.
Da sind wir jetzt alle sehr gespannt.
mfg.
Stefan hat vermutlich auf einer Cray das Programmieren gelernt. Die
haben ja bekanntlich auch eine Endlosschleife innerhalb von 6 Stunden
abarbeiten können.
Do Ma schrieb:> Ein Semikolon obwohl keine Anweisung vorhanden ist!? Ok.
Das Semikolon IST die Anweisung.
Auch in C gibt es die leere Anweisung.
technisch gesehen gehört in
1
while(1);
das Semikolon nicht zum while, sondern bildet seine eigene, eben die
leere Anweisung. Folgt man den üblichen Formatierregeln, die besagen,
dass die abhängige Anweisung im Fall einer Schleife in die nächste Zeile
kommt und eingerückt wird, wie zb in
1
while(i<10)
2
printf("%d",i++);
dann würde konsequenterweise diese Endlosschleife so geschrieben ...
1
while(1)
2
;
... den die abhängige Anweisung besteht nur aus der leeren Anweisung,
die durch ein Semikolon abgeschlossen wird.
Stefan schrieb:>> Und eine Auf-der-Stelle-Trampel-Schleife wird niemals wegoptimiert.>> Dann lese den Code NOCHMAL (und diesmal aufmerksam) durch. Das ist KEINE> Auf-der-Stelle-Trampel-Schleife sondern ein> Schleife-mit-total-leerem-Rumpf.
Und?
Du verwechselst da etwas.
Ein Compiler kann eine Schleife nur dann wegoptimieren, wenn er
nachweisen kann, dass sie NIE ausgeführt wird. Dazu ist es notwendig,
dass er nachweisen kann, dass die Abbruchbedingung nie erfüllt werden
kann bzw. nie TRUE ergibt. Das wird ihm allerdings bei einer
Endlosschleife schwer fallen.
1
while(0)
2
;
kann wegoptimiert werden. Aber
1
while(1)
2
;
kann nicht wegoptimiert werden. Mit dem Inhalt des Schleifenrumpfes,
wieviele und welche Anweisungen da enthalten sind, hat das so (in diesen
beiden konkreten Fällen) erst mal nichts zu tun. Der kommt erst zum
Tragen, wenn es eine Wechselwirkung des Schleifenrumpfes mit der
Abbruchbedingung gibt oder nicht gibt.
Peter II schrieb:> nein das passiert nicht, der compiler darf nichts wegoptimiert was das> verhalten ändert.
Spätestens wenn man zusätzlich ASM verwendet, kommt man drauf, dass der
Gedanke etwas naiv ist. Nicht umsonst gibt es das Schlüsselwort
volatile.
Hat jetzt aber natürlich nichts mit oben genannten Problem zutun.
tomb schrieb:> Peter II schrieb:>> nein das passiert nicht, der compiler darf nichts wegoptimiert was das>> verhalten ändert.>> Spätestens wenn man zusätzlich ASM verwendet, kommt man drauf, dass der> Gedanke etwas naiv ist.
Warum? Hat dir dein Compiler schonmal dein inline-ASM verhunzt?
> Nicht umsonst gibt es das Schlüsselwort> volatile.
Was dazu dient, dem Compiler mitzuteilen, dass sich eine Speicherstelle
anders verhält als sich der C-Standard das vorstellt.
d.H. Solang dein Rechner sich so verhält, wie der Compiler das erwartet,
brauchst du volatile nicht, und es ändert auch nichts am
Programmverhalten.
Εrnst B✶ schrieb:> Was dazu dient, dem Compiler mitzuteilen, dass sich eine Speicherstelle> anders verhält als sich der C-Standard das vorstellt.
volatile teilt den Compiler mit, das Speicherinhalte außerhalb in dem
von ihm einsichtigen Programfluss verwendet werden können und deshalb
nicht wegoptimiert werden dürfen.
Und ja, das braucht man schon öfters mal. IRQs sind auch ein klassisches
Beispiel dafür.
tomb schrieb:> Peter II schrieb:>> nein das passiert nicht, der compiler darf nichts wegoptimiert was das>> verhalten ändert.>> Spätestens wenn man zusätzlich ASM verwendet, kommt man drauf, dass der> Gedanke etwas naiv ist. Nicht umsonst gibt es das Schlüsselwort> volatile.
Das kommt immer drauf an, wie man "Verhalten" definiert und welche
Vorschriften es für den Compiler gibt, die Umgebung einer Codestelle ins
Kalkül zu ziehen.
Und bei Assembler ist der Ofen sowieso aus. Zu diesem Thema hat der
C-Standard im Grunde nur eines zu sagen: Ja, gibt es; aber für Details
und Nebenwirkungen fragen sie ihren Compilerbauer oder die Doku.
tomb schrieb:> Εrnst B✶ schrieb:>> Was dazu dient, dem Compiler mitzuteilen, dass sich eine Speicherstelle>> anders verhält als sich der C-Standard das vorstellt.>> volatile teilt den Compiler mit, das Speicherinhalte außerhalb in dem> von ihm einsichtigen Programfluss verwendet werden können und deshalb> nicht wegoptimiert werden dürfen.>> Und ja, das braucht man schon öfters mal. IRQs sind auch ein klassisches> Beispiel dafür.
Du sprichst von speziellen C Implementierungen, während sich andere
darauf konzentrieren möchten, was der Sprachstandard dazu zu sagen hat.
Standard C hat keine Notation für IRQs oder Memory Mapped Devices oder
atomaren Zugriff oder Interrupts im Generellen oder Shared Memory oder
....
All das kommt im ISO Dokument nicht vor. Man hat sich auf ein paar
Schlüsselwörter geeinigt und der gefordertes Verhalten definiert welche
in den genannten Themenkreisen nützlich und notwendig sind, ohne diese
Themenkreise selbst in den Standard mit aufnehmen zu müssen.
Nicht die Dinge durcheinander werfen, sonst sind Missverständnisse
vorprogrammiert.
Wenn er das while(1); Wegoptimieren würde dann würde der PC einfach
immer weiter inkrementiert und der Blödsinn der dahinter steht
ausgeführt. Da nicht spezifiziert ist was dahintersteht würden eventuell
komische Sachen passieren. Dannn würde irgendwann der PCam Ende des
Speichers ankommen Überlaufen und wieder bei Adresse 0 anfangen
(warscheinlich Reset vektor), das Programm würde erneut ausgeführt usw.
Dies wäre (wenn es so wäre, was es nicht ist!) eindeutig eine
Unzulässige Optimierung.
Es ist halt schon ein unterschied ob ich einen Text auf dem UART ausgebe
und danch in einer Endlosschlleife warte oder ob ich den Text ausgebe
und danach nochmal ausgebe usw.
Εrnst B✶ schrieb:> tomb schrieb:>> Peter II schrieb:>>> nein das passiert nicht, der compiler darf nichts wegoptimiert was das>>> verhalten ändert.>>>> Spätestens wenn man zusätzlich ASM verwendet, kommt man drauf, dass der>> Gedanke etwas naiv ist.
Nö, das gilt immer noch.
Wenn du mit deinem ASM-Code allerdings das Verhalten änderst ohne es
dem Compiler mitzuteilen, ist dein Code fehlerhaft, nicht der Compiler.
> Warum? Hat dir dein Compiler schonmal dein inline-ASM verhunzt?>>> Nicht umsonst gibt es das Schlüsselwort volatile.>> Was dazu dient, dem Compiler mitzuteilen, dass sich eine Speicherstelle> anders verhält als sich der C-Standard das vorstellt.
Aber nicht bei "asm volatile". Da hat "volatile" es eine andere
Bedeutung.
Und in folgendem Beispiel auch:
1
#include<stdio.h>
2
3
typedefintfn(constchar*);
4
5
voidcall(volatilefnf,constchar*str)
6
{
7
f(str);
8
puts("Mitte\n");
9
}
10
11
intmain()
12
{
13
call(puts,"Start\n");
14
call(puts,"Ende\n");
15
16
return0;
17
}
Preisfrage
Was ist die Ausgabe des obigen C-Programms?
p.s. Einfach durch den Compiler jagen und schauen was der draus macht
ist laaangweilig...
Johann L. schrieb:> Was ist die Ausgabe des obigen C-Programms?
Ich bekomme beim kompilieren Warnungen.
Bitte erklär das Verhalten. ich kann es überhaupt nicht nachvollziehen,
weiß aber auch nicht, was das volatile in dem Zusammenhang überhaupt für
einen Zweck haben soll.
Vlad Tepesch schrieb:> Ich bekomme beim kompilieren Warnungen.
Alle Warnungen bekommt man zumindest bei gcc weg, indem man vor main()
noch die Zeile einfügt:
1
volatilefnputs;
Wieder was gelernt heute... Hoffentlich brauche ich das nie.
Mark Brandis schrieb:> Bei mir gibt es dann die folgende Warnung mit gcc Version 3.4.5 (sowohl> bei Übersetzung mit -Wall als auch ohne):>> warning: `noreturn' function returns non-void value
Das ist auch eine vernünftige Warnung (ich kann jetzt nicht
nachvollziehen, warum ich die nicht bekommen habe).
Es wäre aber kein Problem, ein ähnliches Beispiel zu schreiben, um ohne
Warnungen ein undefiniertes Verhalten zu bekommen: Man lügt den Compiler
an, indem man sagt: "Aus dieser (void-)Funktion wird nicht zurückgekehr,
optimiere entsprechend." Sobald Aufrufer und Implementierer in
unterschiedlichen Übersetzungseinheiten liegen, kann der Compiler diese
Lüge kaum noch aufdecken und anwarnen.