Forum: Compiler & IDEs Warum Keil (oder andere unfreie Compiler) statt SDCC?


von Philipp Klaus K. (pkk)


Lesenswert?

Guten Abend.

Ich interessiere mich für die Gründe, aus denen manche Programmierer für 
Architekturen, die vom Small Device C Compiler (SDCC) unterstützt 
werden, nichtfreie Compiler  (Keil, IAR, Cosmic, Raisonance, etc) 
einsetzen. Es wäre schön, wenn die Antworten neben den Gründen auch die 
jeweiligen Architekturen nennen würden.

von Εrnst B. (ernst)


Lesenswert?

Lang ist's her, vermute eine 2.x.0-Version:

PIC: Libraries waren nicht kompatibel, müssten aufwändig angepasst 
werden, um mit dem SDCC zusammenzuspielen. (z.B. das USB-Framework für 
16F4550 &co)

Inzwischen sind die PIC-Targets im SDCC unmaintained, oder?

von Philipp Klaus K. (pkk)


Lesenswert?

Εrnst B. schrieb:
> Inzwischen sind die PIC-Targets im SDCC unmaintained, oder?

Ja. Immerhin sind die von den PIC-Ports verwendeten gputils nun 
anscheinend wieder maintained, so dass ein zukünftiger Maintainer der 
PIC-Ports in SDCC eine Sorge weniger hätte.

von DerEgon (Gast)


Lesenswert?

Zu den Gründen könnte gehören, daß mehr als nur ein Compiler benötigt 
wird, sondern auch eine Debugunterstützung. PICs beispielsweise kann man 
mit dem Microchip Studio beglücken, und da funktionieren PicKit, Mplab 
Snap etc. als Programmier- und Debuginterfaces.

Und wenn so eine Entwicklungsumgebung eines Herstellers eh' schon 
verwendet wird, und nur eine neue Architektur hinzukommt, muss der 
Nutzer sich nicht umstellen. Microchip Studio (um beim Beispiel zu 
bleiben) kann eben als Nachfolger des Atmel Studio nicht nur AVRs, 
sondern auch PICs und Atmel-ARM (SAMDirgendwas) programmieren.

Für AVRs steckt da ein avrgcc drin, aber es gibt auch den 
microchipeigenen XC8 als Compiler (der ohne zusätzliche Lizenz nur 
eingeschränkt, d.h. ohne Optimierung verwendbar ist).

In manchen Entwicklungsszenarien ist eine Zertifizierung nach 
irgendwelchen Richtlinien erforderlich (MISRA, kann wohl von IAR geboten 
werden).

Es gibt also eine ganze Latte von Gründen-

von Frank K. (fchk)


Lesenswert?

DerEgon schrieb:
> Zu den Gründen könnte gehören, daß mehr als nur ein Compiler benötigt
> wird, sondern auch eine Debugunterstützung. PICs beispielsweise kann man
> mit dem Microchip Studio beglücken, und da funktionieren PicKit, Mplab
> Snap etc. als Programmier- und Debuginterfaces.

Genau. Und das nicht nur für PIC16, sondern auch für PIC18, PIC24 und 
PIC32. Es macht da einfach gar keinen Sinn, etwas anderes als das 
Microchip-Komplettpaket zu nehmen, weil es einfach Zeit spart und die 
Arbeitszeit das eigentlich teure ist und nicht die Lizenzen.

Ich verdiene damit mein Geld. Es ist mir daher recht egal, ob der 
Compiler frei gemäß GNU-Richtlinien ist oder nicht, weil die Kosten vom 
jeweiligen Projekt getragen werden. Ich habe hier auch einen Kollegen, 
der IAR für MSP430 benutzt, weil den Entscheidern das Risiko, dass bei 
einem (nicht notwendigen) Wechsel irgendwas beim Kunden nachher nicht 
mehr funktioniert, zu groß ist.

In einem universitären Umfeld wird das sicher anders sein als in einem 
Unternehmen.

fchk

von Heizer (Gast)


Lesenswert?

DerEgon schrieb:
> In manchen Entwicklungsszenarien ist eine Zertifizierung nach
> irgendwelchen Richtlinien erforderlich (MISRA, kann wohl von IAR geboten
> werden).

Das dürfte in der Industrie ein Hauptgrund sein. Gegenüber den 
Personalkosten spielen die Lizenzkosten keine ernsthafte Rolle. Ein 
Compiler bzw. eine Ganze IDE mit "Stempel drauf" und integrierten Checks 
schon.
Wir haben mal für den AVR den gcc Assebmler-Output gegenüber IAR AVR 
verglichen, und uns dann ganz schnell für den IAR entschieden (okay 
schon eine Weile her, das war 2012).
Entscheidend dürfte für die meisten professionellen Benutzer sein, ob 
der Compiler/IDE-Hersteller einen "Guten Draht" zum 
µC-Hersteller/Designer hat, und so möglichst schnell und gut die 
Fähigkeiten oder Beschränkungen eines µC´s (oder einer Architektur) 
auszunutzen.

Gruß

von ... (Gast)


Lesenswert?

SDCC:
Schon die Dokumentation der Installation ist lückenhaft.
Er erfordert viele zu setzende Umgebungsvariable.
Die muss man "raten" und den Inhalt auch.
Welche Teile des Compilers und der Binuteils wohin gehören
ist das nächste Ratespiel.

Ich musste vor vielen Jahren MSC5 von Hand installieren,
weil der Installer mit der speziellen Grafikkarte nicht konnte.
Selbst das ging wesentlich einfacher.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Heizer schrieb:
> Gegenüber den Personalkosten spielen die Lizenzkosten keine ernsthafte
> Rolle.

Nicht unbedingt immer.

In meiner Zeit bei Atmel (auch schon eine Weile her) hat mich mal ein 
Atmel-Mitarbeiter angesprochen, weil ein namhafter Kunde den IAR durch 
AVR-GCC ablösen wollte. Der Grund: sie wollten gern nightly builds in 
einer Serverfarm einführen (was man heute als "CI" bezeichnen würde), 
und für eine solche Nutzung wären ihnen die IAR-Lizenzkosten explodiert.

Aber für die von Philipp genannten Targets dürfte sowas eher irrelevant 
sein. Da ist ein AVR genauso wenig dabei wie ein ARM.

von K. H. (hegy)


Lesenswert?

Bei meinem Ex-Chef ging es auch um Verantwortung, also der Lieferant von 
der Software wird verantwortlich gemacht wenn irgendwas ist. Und dieses 
irgendwas kann z. B. sein,
- wenn nach einem Update irgendwas nicht mehr läuft,
- wenn es beim Debuggen hakt und klemmt, dass die kurzfristig eine 
Lösung erarbeiten (müssen),
- oder wenn man Sonderwünsche hat,
- ...

Jedenfalls gibt es jemanden, den man treten und ggf. 
Schadensersatzpflichtig machen kann, wenn es nicht rund läuft und bei 
den engen Terminen es zu Problemen kommt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

K. H. schrieb:
> Jedenfalls gibt es jemanden, den man treten und ggf.
> Schadensersatzpflichtig machen kann, wenn es nicht rund läuft und bei
> den engen Terminen es zu Problemen kommt.

Und das hat je funktioniert und war nicht durch irgendwelche AGB eh 
ausgeschlossen?

von K. H. (hegy)


Lesenswert?

Das weiß ich nicht, jedenfalls war das die Begründung von unserem 
(unfähigen) Gruppenleiter (GL). Ansonsten hätte unsere Fa. schon 
mehrfach National Instruments (NI) in den Arsch treten müssen, aber ich 
denke, unser GL hatte dazu keine "Eier in der Hose" und hat das Problem 
erstmal auf die Kollegen abgewälzt, solange er sich aus Karrieregründen 
die Finger nicht schmutzig macht. Also, wenn es hakt und klemmt sind die 
eigenen Mitarbeiter erstmal Schuld und wenn die beweisen können, dass 
sie nichts dafür können (ja, sie müssen ihre Unschuld beweisen), dann 
sind sie irgendwie immer noch Schuld. Erst wenn man den unfähigen GL 
wegen Verzögerungen anzählen könnte, wurde der aktiv und hat jemanden 
aus unserer Gruppe damit beauftragt, bei Fa. NI nachzuhaken und Druck zu 
machen. Das gab es als zusätzliche Aufgabe oben drauf, wir hatten ja 
Zeit genug, eine Woche hat ja bis zu 148 mögliche Arbeitsstunden.

Jedenfalls was er Open Source Zeug gegenüber ziemlich voreingenommen, 
das war bestenfalls Bastelware.

Übrigens hatten wir in solchen Sachen die meisten Probleme mit NI.

von Lothar (Gast)


Lesenswert?

Philipp Klaus K. schrieb:
> die vom Small Device C Compiler (SDCC) unterstützt werden

Wir hatten doch hier mal über die fehlende Eclipse Integration 
gesprochen.

FTDI hatte ja einen Versuch gemacht, das Ergebnis war aber nicht 
optimal, und inzwischen haben die ja aufgegeben:

https://www.ftdichip.com/old2020/Products/ICs/FT51.html

Silabs hat ja die Vereinbarung mit ARM/Keil für die kostenfreie Nutzung, 
dennoch gab es einen Versuch mit Eclipse/Simplicity Studio und sdcc, 
läuft aber bis Stand heute nicht:

https://community.silabs.com/s/question/0D51M00007xeGALSA2/add-the-sdcc-compiler-to-simplicity-studio

sdcc mag besser sein als Keil, aber wenn man dafür nicht aus 
Eclipse/Simplicity Studio flashen/debuggen kann, und mit HEX Datei und 
Bootloader anrücken muss ...

von S. R. (svenska)


Lesenswert?

Philipp Klaus K. schrieb:
> Es wäre schön, wenn die Antworten neben den Gründen auch die
> jeweiligen Architekturen nennen würden.

Beide Beispiele beziehen sich auf den Z80. Haben zwar nichts mit den 
kommerziellen Compilern zu tun, aber vielleicht hilft es ja trotzdem.

David Given (https://github.com/davidgiven/cpmish) wechselt von SDCC zu 
ACK, unter anderem weil SDCC "buggy" ist. Der Code ist zwar wesentlich 
schlechter, kann dafür aber 8080.

FUZIX (https://github.com/EtchedPixels/FUZIX) beschwert sich im Code oft 
über SDCC-Bugs und entsprechende Workarounds. Allerdings ist Z80 auch 
ein Primärtarget für das Projekt.

Was den kommerziellen Einsatz betrifft, liegen die Gründe eher in den 
nicht-technischen Bereichen, die bereits genannt wurden.

Wir haben zwar nichts mit kleinen Controllern zu tun, aber nutzen Clang, 
weil unsere Lieferanten das so vorschreiben. Würde da etwas anderes 
dranstehen, würden wir auch etwas anderes nutzen, egal was es kostet. Da 
hängen Haftungsfragen und Zertifizierungen dran, und jeder 
Patch/Workaround in 3rd-party-code müsste von uns bis in die Ewigkeit 
selbst gepflegt werden, weil "upstream" die vermutlich nicht integrieren 
würde.

Linux hat sich auch so sehr lange geweigert, Clang-Fixes zu integrieren.

von Philipp Klaus K. (pkk)


Lesenswert?

S. R. schrieb:
> Philipp Klaus K. schrieb:
>> Es wäre schön, wenn die Antworten neben den Gründen auch die
>> jeweiligen Architekturen nennen würden.
>
> Beide Beispiele beziehen sich auf den Z80. Haben zwar nichts mit den
> kommerziellen Compilern zu tun, aber vielleicht hilft es ja trotzdem.

Der z80-Port unterscheidet sich diesbezüglich deutlich von mcs51, sie 
sind in gewisser Weise Gegenteile: Bei mcs51 gab es in den letzten 
Jahren nur wenige Änderungen, die meisten davon Bugfixes. Und Bugs 
werden dort nur sehr selten gefunden. Bei z80 gab es dagegen eine sehr 
aktive Entwicklung, vor allem um Codegröße und -geschwindigkeit zu 
verbessern.
Das führt dazu, dass im aktuellen Release 4.2.0 für mcs51 nahezu immer 
fehlerfreier Code generiert wird, der aber nicht sonderlich effizient 
ist. Für z80 wird dagegen deutlich effizienterer Code generiert; 
bekanntwerdende Bugs für z80 werden meist zeitnah behoben, aber durch 
die vielen Änderungen zur Verbesserung der Effizienz entstanden 
natürlich auch mehr Bugs. Und wenn man, wie bei FUZIX üblich, mit einem 
hohen Wert für --max-allocs-per-node kompiliert erhält man noch stärker 
optimierten Code (um den Preis einer höheren Compilerlaufzeit, und 
dessen, dass man dann SDCC auf eine Weise verwendet, die nicht so 
ausführlich getestet wurde).

Allgemein ist SDCC aber in den letzten 2 Jahrzehnten deutlich 
zuverlässiger geworden. Insbesondere hat SDCC auch eine großen Teil der 
Testsuite von GCC übernommen, wodurch nochmal einige Bugs gefunden und 
behoben wurden.

von Philipp Klaus K. (pkk)


Lesenswert?

Vielen dank für die Antworten. Da es inzwischen hier und andernorts 
einige gab, und nun nur noch sehr langsam weitere eintreffen, möchte ich 
eine kurze Zusammenfassung geben.

Eine Antwort möchte ich hier in voller Länge zitieren, da sie sehr 
direkt die beiden meistgenannten Gründe enthält:

"In my case the customer requested SDCC based project but it failed to 
compile into the small flash size. Debugging was quite difficult. Using 
the Simplicity Studio and Keil Compiler pairing made the code small 
enough to fit into the device and made debugging much easier."

Die 3 meistgenannten Gründe gegen SDCC waren:

* Mangelnde Effizienz des von SDCC generierten Codes.
* Bessere Debugunterstützung und Integration der nichtfreien Toolchain.
* Verfügbarkeit bezahlten Supports für nichtfreie Compiler.

Meiner Meinung nach ist nun mittelfristig der aussichtsreichste Weg, 
SDCC konkurrenzfähiger gegenüber nichtfreien Compilern zu machen:

0) Verbesserte maschinenunabhängige Optimierungen
1) Verbesserte maschinenabhängige Optimierungen für mcs51
2) Bessere Debugunterstützung und Integration
3) Finden und Beheben von Bugs.

Insgesamt schätze ich den Aufwand auf eine Vollzeitstelle für gut ein 
Jahr. Aber auch mit weniger lässt sich natürlich einiges erreichen.

Punkt 2 Hätte eigentlich bereits im vom BMBF geförderten Projekt 
SDCC-STD-UX angegangen werden sollen, wurde dann aber zugunsten 
verbesserter Unterstützung für C2X zurückgestellt.

: Bearbeitet durch User
von Chris R. (rcc)


Lesenswert?

Jörg W. schrieb:
>> Jedenfalls gibt es jemanden, den man treten und ggf.
>> Schadensersatzpflichtig machen kann, wenn es nicht rund läuft und bei
>> den engen Terminen es zu Problemen kommt.
>
> Und das hat je funktioniert und war nicht durch irgendwelche AGB eh
> ausgeschlossen?

Bei automotive ist das normales Business, wenn der Tier 1 zum 
vertraglich vereinbarten Zeitpunkt nicht liefern kann oder wegen nicht 
zertifizierter Tool-Chain etwas passiert wirds teuer für ihn. Schneller 
(d.h. mit garantierten Reaktionszeiten) Support bei Compilerfehlern ist 
da auch wichtig.

von W.S. (Gast)


Lesenswert?

Philipp Klaus K. schrieb:
> Meiner Meinung nach ist nun mittelfristig der aussichtsreichste Weg,
> SDCC konkurrenzfähiger gegenüber nichtfreien Compilern zu machen:

So, nun ist deine Katze aus dem Sack. Hättes es auch gleich sagen 
können.

Man kann das auch kürzer sagen: der SDCC müßte in allen Punkten besser 
werden, um mitspielen zu können.

Ich hatte sowas ähnliches vor Jahren mit dem GCC bei der Lernbetty 
gemerkt. Im Vergleich zum Keil ist der GCC weitaus hakeliger in der 
Benutzung, kann weniger, ist stellenweise inkompatibel zum Standard 
(__irq und keine Pragmas Arm<-->Thumb) ist unverschämt (kürzt Schleifen, 
die ICH geschrieben habe einfach weg), ist teilweise buggy (Problem 
.thumb versus .thumbfunc) und machte dennoch einen umfänglicheren und 
zugleich langsameren Maschinencode. Der einzige Pluspunkt ist der 
fehlende Preis, was eigentlich nur für private Bastler wichtig ist. Er 
hat dennoch seine Berechtigung, denn es heißt "besser schlecht gefahren 
als gut gelaufen". So ähnlich sehe ich das auch beim SDCC.

W.S.

von Martin H. (horo)


Lesenswert?

Philipp Klaus K. schrieb:
> 1) Verbesserte maschinenabhängige Optimierungen für mcs51

Hallo Philipp,

manchmal treten aber mit steigenden Versionen auch Regressionen auf, die 
mir z.B. bei einer zeitkritischen Anwendung auf die Füße gefallen sind, 
SDCC 3.8 -> SDCC4.0:

https://github.com/Ho-Ro/Hantek6022API/issues/12

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

W.S. schrieb:
> So, nun ist deine Katze aus dem Sack. Hättes es auch gleich sagen
> können.

Das war beim Namen des Threadstarters aber von vornherein klar.

> Im Vergleich zum Keil ist der GCC weitaus hakeliger in der
> Benutzung, kann weniger, ist stellenweise inkompatibel zum Standard
> (__irq und keine Pragmas Arm<-->Thumb)

Was haben Implementierungs-Eigenheiten (alles, was mit zwei 
Unterstrichen beginnt) und Pragmas mit "Standard" zu tun?

Wenn du dann noch den IAR ins Spiel bringst, wird der solche Dinge 
nochmal anders handhaben – ist sein gutes Recht. Dinge wie das 
Umschalten des Maschinenmodells oder Interrupts sind schlicht und 
ergreifend eben kein Standard.

Ich hätte gern für mein aktuelles Projekt lieber den GCC genommen, aber 
ich habe Herstellerbibliotheken mit ELF-Modulen, die Keil-proprietäre 
Details enthalten (wenngleich ich gar nicht denke, dass sie das 
bräuchten), und bei denen der GNU-Linker es daher als inkompatibel 
ablehnt, sie zu linken. $$$ ist in dem Fall zwar nicht das Thema 
(Lizenzen bezahlt $FIRMA), aber den ganzen Keil-uVision-Salat gibt's 
halt nur für Windows, also muss ich ihn in einer VM laufen lassen, und 
dort hat er sich wiederum hakelig damit, auf einem Netzwerklaufwerk zu 
compilieren – er findet dann sämtliche Include-Files nicht. 
Herstellersupport dafür? Kannste vergessen, "VM is not officially 
supported" lautet die lapidare Antwort.

Ich weiß, ist off-topic hier, denn es war nach SDCC gefragt, aber zeigt, 
dass es durchaus Kriterien geben kann, warum man einen kommerziellen 
Compiler eigentlich gar nicht nehmen möchte aber nehmen muss. (Die MCU 
ist völlig proprietär, und wahrscheinlich darf ich hier nicht einmal 
schreiben, welche es ist, weil das schon unter NDA fällt.)

: Bearbeitet durch Moderator
von Philipp Klaus K. (pkk)


Lesenswert?

> Man kann das auch kürzer sagen: der SDCC müßte in allen Punkten besser
> werden, um mitspielen zu können.

Nein. Die Antworten haben gezeigt, wo SDCC besser werden müsste. 
Umgekehrt erkennt man daran aber auch, wo SDCC schon gut genug ist¹. Und 
sie haben gezeigt, dass es durchaus möglich ist durch technische 
Verbesserungen an SDCC die Position von SDCC gegenüber den nichtfreien 
Compilern zu verbessern².

¹ Z.B. Hat sich niemand bezüglich SDCC über Compilerlaufzeit, 
Ressourcenbedarf des Compilers oder mangelnde Unterstützung von 
C-Standards beschwert.
² Es gab zwar durchaus einige, die sich aufgrund von Empfehlungen der 
µC-Hersteller gegen SDCC entschieden, wegen mangelnder Unterstützung von 
SDCC in Bibliotheken dritter, oder aufgrund mangelnder Zertifizierungen 
von SDCC, aber das war eine Minderheit.

von S. R. (svenska)


Lesenswert?

Philipp Klaus K. schrieb:
> Z.B. Hat sich niemand bezüglich SDCC über Compilerlaufzeit,
> Ressourcenbedarf des Compilers oder mangelnde Unterstützung
> von C-Standards beschwert.

Wieder bezogen auf Z80: SDCC ist einfach sehr langsam, aber mangels 
guter Alternativen muss man damit einfach leben. Da Programme in der 
8-Bit-Welt naturgemäß nicht besonders groß sein können, bleiben auch die 
Compilezeiten erträglich.

W.S. schrieb:
> Ich hatte sowas ähnliches vor Jahren mit dem GCC bei der Lernbetty
> gemerkt. Im Vergleich zum Keil ist der GCC weitaus hakeliger in der
> Benutzung, kann weniger, ist stellenweise inkompatibel zum Standard
> (__irq und keine Pragmas Arm<-->Thumb) ist unverschämt (kürzt Schleifen,
> die ICH geschrieben habe einfach weg), ist teilweise buggy (Problem
> .thumb versus .thumbfunc) und machte dennoch einen umfänglicheren und
> zugleich langsameren Maschinencode.

Vielleicht solltest du dazu schreiben, dass du nicht in C 
programmierst, sondern nur in einer Sprache, die ungefähr so ähnlich 
aussieht.

von Nop (Gast)


Lesenswert?

W.S. schrieb:
> ist unverschämt (kürzt Schleifen,
> die ICH geschrieben habe einfach weg)

Das liegt an Deinen bekanntermaßen dürftigen C-Kenntnissen - nicht am 
Compiler.

von W.S. (Gast)


Lesenswert?

Nop schrieb:
> Das liegt an Deinen bekanntermaßen dürftigen C-Kenntnissen - nicht am
> Compiler.

Und du meinst, ein Compiler darf meine Kenntnisse über irgend etwas 
abfragen und wenn es ihm nicht paßt, mir einfach mein Geschriebenes 
wegstreichen? Nö, sowas akzeptiere ich nicht. Der Keil macht solche 
Faxen übrigens nicht. Und der FCC911 übrigens auch nicht. Das ist der 
für die Fujitsus. Seltsam, gelle? Ich sehe auch dieses Detail anders als 
du, nämlich daß du und viele andere zu sehr an den GCC gewöhnt sind und 
nun alles andere für Geisterfahrer halten. So herum.

W.S.

von Nop (Gast)


Lesenswert?

W.S. schrieb:

> Und du meinst, ein Compiler darf meine Kenntnisse über irgend etwas
> abfragen und wenn es ihm nicht paßt, mir einfach mein Geschriebenes
> wegstreichen?

Ein C-Compiler darf (nicht: muß!) Dinge unter der as-if-Regel streichen, 
wie das im C-Standard vorgesehen ist. Wenn Du den C-Standard nicht 
kennst, d.h. Du kannst kein C, ist das Dein Problem und nicht das des 
Compilers.

von Gcc (Gast)


Lesenswert?

Er fragt keine Kenntnisse ab, sonder setzt das Verhalten um, was ihm in 
der Programmiersprache beschrieben wurde. Da es kein C–Keyword für 
„Warte mal kurz“ gibt, stellt er fest das die Schleife keine Änderung am 
Programmzustand hervorruft und genau das übersetzt er dann dann in ein 
„don‘t execute anything“. Und das so schnell wie irgend möglich.

Es gibt in C auch die Möglichkeit zu erklären, das da was passiert, was 
der Compiler nicht sieht (volatile) und dann respektiert er das. Nur 
hinschreiben muß es der Programmierer.

von Philipp Klaus K. (pkk)


Lesenswert?

S. R. schrieb:
> Philipp Klaus K. schrieb:
>> Z.B. Hat sich niemand bezüglich SDCC über Compilerlaufzeit,
>> Ressourcenbedarf des Compilers oder mangelnde Unterstützung
>> von C-Standards beschwert.
>
> Wieder bezogen auf Z80: SDCC ist einfach sehr langsam, aber mangels
> guter Alternativen muss man damit einfach leben.

Beim Z80 wären die Alternativen sdcc mit einem kleinen Wert für 
--max-allocs-per-node, sowie zcc und ack. Die sind alle ebenfalls frei, 
aber generieren üblicherweise schlechteren Code. Umgekehrt kann man sdcc 
mit hohem Wert für --max-allocs-per-node oft noch langsamer machen und 
dafür noch etwas besseren Code erhalten.

von A. S. (Gast)


Lesenswert?

Philipp Klaus K. schrieb:
> nichtfreie Compiler ... einsetzen.

Ist das nicht die gleiche Frage wie Linux/Windows, Libre/MS, Gimp/PS 
etc?

Also Total_Cost_of_Ownership, Killerfeatures, Ausfallrisiko, 
Integration, Kundenanforderungen, Gewohnheit, Schmiergeld (Seminare 
etc.), ... nicht unbedingt in der Reihenfolge.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

A. S. schrieb:
> Ist das nicht die gleiche Frage

Nein, sie war deutlich konkreter gestellt, und wenn du dir den Rest des 
Threads ansiehst, dann vor allem deshalb, weil Philipp offenbar wissen 
möchte, an welcher Stelle er weitere Manpower am besten ansetzen sollte.

von W.S. (Gast)


Lesenswert?

Gcc schrieb:
> Er fragt keine Kenntnisse ab, sonder

Gcc schrieb:
> Er fragt keine Kenntnisse ab, sonder...

Das ist mir klar, diese Bemerkung war auch nur zum Zwecke der 
Vedeutlichung.
Um es mal klar zu sagen: von einem Compiler erwarte ich, daß er das, was 
ich haben will, optimal von der Sprache der Notation in entsprechenden 
Maschinencode übersetzt, aber NICHT, daß er an meinem Geschriebenen 
herum mäkelt und nur dann, wenn es im Sinne seiner Programmierer ist, 
das Zeug übersetzt.

Wenn das nicht gegeben ist, dann ist so ein Compiler nicht geeignet für 
alle Firmware, die in irgend einer Weise mit Hardware zu tun hat. Und 
ein Standard, der derartige Eigenmächtigkeiten sanktioniert, taugt nur 
für die Tonne.

Aber zurück zum Thema, was man besser "warum nehmen die Leute nicht NUR 
den SDCC?" hätte nennen können. Der Philipp schrieb:
> 0) Verbesserte maschinenunabhängige Optimierungen
> 1) Verbesserte maschinenabhängige Optimierungen für mcs51
> 2) Bessere Debugunterstützung und Integration
> 3) Finden und Beheben von Bugs.

Tja, ist das nicht alles, wenn die Rede ist von einem Compiler?
Also, was denn sonst noch - außer Pillepalle?

W.S.

von Keine Betty kann hier helfen (Gast)


Lesenswert?

W.S. schrieb:
> Um es mal klar zu sagen: von einem Compiler erwarte ich, daß er das, was
> ich haben will, optimal von der Sprache der Notation in entsprechenden
> Maschinencode übersetzt,

Soweit, so schön. Das macht annähernd jeder Compiler so, sofern er 
nicht irgendwas zusammengefrickeles aus dem 1. Semester der 
Informatik-Vorlesung ist.

> aber NICHT, daß er an meinem Geschriebenen herum mäkelt

Dann schalte halt alle Warnungen aus, wenn Du zu blöd bist, C 
programmieren lernen zu wollen. Leb' dann aber auch mit den Ergebnissen, 
ohne rumzuheulen.

> und nur dann, wenn es im Sinne seiner Programmierer ist,
> das Zeug übersetzt.

Das ist drollig: Ein standardkonformer C-Compiler, der den Code (oder 
Kot?) des Lernbetty-Großmeisters nicht so übersetzen will, wie es der 
Herr Großmeister will, wird abgelehnt.

Wielange dauert es eigentlich noch, bis Du a) entweder C programmieren 
lernst oder b) Dich anderen Dingen zuwendest?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

W.S. schrieb:
> Um es mal klar zu sagen: von einem Compiler erwarte ich, daß er das, was
> ich haben will, optimal von der Sprache der Notation in entsprechenden
> Maschinencode übersetzt

Genau das macht ein Compiler übrigens, wenn er
1
  for (int i = 0; i < 10000; i++)
2
  { /* nothing */ }

zu nichts übersetzt, denn "nichts" ist sowohl von der Laufzeit als 
auch vom Speicherverbrauch her die optimale Umsetzung einer Schleife, 
die schlicht nichts macht. Die Zuweisung von Daten zu einer Variablen, 
die man hinterher nicht wieder abfragt, ist eben halt aus Sicht eines 
Compilers "nichts".

von Zeno (Gast)


Lesenswert?

Jörg W. schrieb:
> W.S. schrieb:
>> Um es mal klar zu sagen: von einem Compiler erwarte ich, daß er das, was
>> ich haben will, optimal von der Sprache der Notation in entsprechenden
>> Maschinencode übersetzt
>
> Genau das macht ein Compiler übrigens, wenn er
> 1  for (int i = 0; i < 10000; i++)
> 2  { /* nothing */ }
>
> zu nichts übersetzt,
Der Compiler meint, daß es nichts sein soll. Man könnte so etwas als 
eine Art Verzögerung einsetzen, da jeder Befehl eine bestimmte Anzahl 
von Taktzyklen benötigt. Ob das am Ende guter Programmierstil ist sei 
mal dahin gestellt, aber es würde vom Prinzip her funktionieren.

Vielleicht könnte der W.S. einfach mal ein Beispiel bringen.

von Betty hilft auch hier nicht weiter (Gast)


Lesenswert?

Wer C programmieren kann, wüsste, wozu "volatile" verwendet werden kann.

Wer sich hingegen weigert, dem hilft auch keine "Lernbetty".

von S. R. (svenska)


Lesenswert?

Zeno schrieb:
> Vielleicht könnte der W.S. einfach mal ein Beispiel bringen.

Der W.S. könnte auch einfach in C programmieren anstatt in einer 
Programmiersprache, die nur so aussieht wie C. Das ist nämlich das 
eigentliche Problem.

von Zeno (Gast)


Lesenswert?

S. R. schrieb:
> Der W.S. könnte auch einfach in C programmieren anstatt in einer
> Programmiersprache, die nur so aussieht wie C. Das ist nämlich das
> eigentliche Problem.
Wenn Du meinst.

von Zeno (Gast)


Lesenswert?

Betty hilft auch hier nicht weiter schrieb:
> Wer C programmieren kann, wüsste, wozu "volatile" verwendet werden kann.
>
> Wer sich hingegen weigert, dem hilft auch keine "Lernbetty".
Man muß ja mit W.S. nicht immer einer Meinung sein und in manchen Dingen 
ist er sicher auch etwas speziell. Dennoch kann man sich ja auch das was 
er z.B. mit der Lernbetty verbrochen hat ansehen. Ich habe das vor ein 
paar Jahren mal getan und mir das ganze Betty Geraffel herunter geladen. 
Es hat so funktioniert wie er es beschrieben hat - völlig problemlos vom 
Compilieren der Quellen, Übertragen des Compilats auf die Betty und die 
Funktion selbst. Also für einen der kein C kann nicht ganz schlecht. Die 
Dokumentation zu seinem Projekt ist auch nicht schlecht gemacht, die 
Mehrzahl solcher Projektdokumentationen, wenn es denn überhaupt welche 
gibt, ist deutlich schlechter.

Ansonsten stell doch mal selbst ein solches Projekt auf die Beine und 
beweise wie man es besser macht. Deine 2 Post in diesem Thread sind 
bisher nur unqualifiziertes Geblöke ohne jegliche Substanz.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Zeno schrieb:
> Der Compiler meint, daß es nichts sein soll. Man könnte so etwas als
> eine Art Verzögerung einsetzen, da jeder Befehl eine bestimmte Anzahl
> von Taktzyklen benötigt.

Es gibt aber in C keinen "Befehl", und es gibt auch keine 
vorgeschriebenen Mindestausführungszeiten. Das würde letztlich der 
Forderung nach möglichst optimaler Umsetzung des aufgeschriebenen Codes 
zuwider laufen.

GCC hatte früher für diesen Konstrukt tatsächlich eine "Sonderlocke" 
implementiert, aber das war zusätzlicher Aufwand, just diese Situation 
("toter Code, der stehen bleiben soll") zu erkennen, und irgendwann 
haben sie halt diese Sonderlocke abgeschafft.

von Zeno (Gast)


Lesenswert?

Jörg W. schrieb:
> Es gibt aber in C keinen "Befehl", und es gibt auch keine
> vorgeschriebenen Mindestausführungszeiten. Das würde letztlich der
> Forderung nach möglichst optimaler Umsetzung des aufgeschriebenen Codes
> zuwider laufen.
Ach Jörg, jetzt hör mal mit dieser Erbsenzählerei auf, Du bist 
intelligent genug um zu wissen worauf ich hinaus wollte. Ob man das nun 
Befehl, Anweisung oder wie auch immer benennt ist am Ende doch völlig 
Rille. Schlußendendlich macht der Compiler am Ende daraus eine Folge von 
Instruktionen für die CPU die entsprechend umgesetzt werden. Für ein i++ 
sind nun mal eine bestimmte Anzahl von Taktschritten erforderlich um 
dies umzusetzen, am Ende wird die weitere Befehlsausführung um genau die 
Zeit die für die Ausführung erforderlich ist verzögert. Es könnte also 
durchaus sein, das sich der Programmierer was dabei gedacht hat und 
insofern wäre es schon wünschenswert, wenn der Compiler das umsetzt was 
man hinschreibt, zumindest solange es sich um erlaubte Codesequenzen 
handelt. Der Compiler kann ja in solch einem Fall eine Warnung ausgeben 
und es dem Programmierer überlassen ob er es denn so stehen lassen will.

von Philipp Klaus K. (pkk)


Lesenswert?

Zeno schrieb:
> Für ein i++
> sind nun mal eine bestimmte Anzahl von Taktschritten erforderlich um
> dies umzusetzen, am Ende wird die weitere Befehlsausführung um genau die
> Zeit die für die Ausführung erforderlich ist verzögert. Es könnte also
> durchaus sein, das sich der Programmierer was dabei gedacht hat und
> insofern wäre es schon wünschenswert, wenn der Compiler das umsetzt was
> man hinschreibt, zumindest solange es sich um erlaubte Codesequenzen
> handelt.

Diesen Thread habe ich begonnen, da SDCC-Entwickler nur wenig über jene 
wissen, die SDCC nicht verwenden. Über die Nutzer von SDCC wissen wir 
dagegen deutlich mehr, da diese ja über Mailinglisten, Tracker, etc mit 
uns in Kontakt sind.

Nutzer mit obiger Ansicht gibt es durchaus, aber es ist eine kleine, 
schrumpfende Minderheit. Ja, der Programmierer hat sich etwas gedacht, 
als er das ++ schrieb. Aber heutzutage ist das ++ (oder was auch immer) 
oft in einem Makro oder einer inline-Funktion, die dann mit konstanten 
Parametern aufgerufen werden, die dann dazu führen, dass jenes ++ gar 
nicht gebraucht wird. Und der Programmierer hat sich gedacht, dass das 
kein Problem ist, da der Compiler es ja wegoptimieren kann, wenn es 
nicht gebraucht wird.

Nur mal ein Beispiel: An SDCC wird häufig kritisiert, dass es jede 
Funktion, die in einer Quellcodedatei steht, auch in die Binärdatei 
kompiliert (wenn man also mehrere .c zu .rel kompiliert und diese dann 
zusammenlinkt, ohne eine .lib zu verwenden), selbst wenn die betreffende 
Funktion gar nicht aufgerufen wird. Da geht es also nicht mal um ein 
einzelnes ++ oder eine leere Schleife, sondern um ganze Funktionen, von 
denen die Programmierer erwarten, dass der Compiler diese wegoptimiert!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Zeno schrieb:
> Es könnte also durchaus sein, das sich der Programmierer was dabei
> gedacht hat

Wie Philipp schon schreibt: oft genug hat der Programmierer das nicht so 
direkt hingeschrieben, sondern es versteckt sich innerhalb von irgendwas 
anderem. Wenn du 'i = i * 2' schreibst, erwartest du ja auch nicht, dass 
dann der (bei Fehlen von Multiplikationsbefehlen in der CPU in einer 
Bibliothek sitzende) Code für eine Multiplikation mit 2 ausgeführt wird, 
wenn der Compiler eigentlich auch feststellen kann, dass er stattdessen 
viel einfacher nur ein Bit nach links schieben muss.

Wenn du zehnmal 'i++' ausführst, ohne dass das Ergebnis verwendet wird, 
erwartest du auch keine 10mal ausgeführte Schleife, wenn die direkte 
Addition einer 10 das gleiche tut.

So ist es eben auch, wenn du in einer Schleife irgendwas aufaddierst, 
das am Ende gar nicht benutzt wird.

Verzögerungen jeglicher Art, insbesondere solche mit einem irgendwie 
definierbaren Zeitverhalten, sind daher maschinenabhängig und lassen 
sich nur entsprechend auf diesem Niveau implementieren. Ob man dafür nun 
in die Schleife simpel einen "NOP" setzt oder ob es eine gut ausgefeilte 
Infrastruktur dafür gibt (wie beim AVR-GCC, bei dem der Compiler 
taktgenaue Verzögerungen nicht nur mit Schleifen sondern auch mit sauber 
gezählten NOPs machen kann), es führt kein Weg dran vorbei, sich sowas 
von Fall zu Fall selbst anzusehen statt den Compiler, von dem man 
erwartet, dass er "optimal von der Sprache der Notation in 
entsprechenden Maschinencode übersetzt" zu beschuldigen, dass er den 
Code wegwirft, der aus seiner Sicht schlicht nichts macht.

: Bearbeitet durch Moderator
von Εrnst B. (ernst)


Lesenswert?

Zeno schrieb:
> Der Compiler kann ja in solch einem Fall eine Warnung ausgeben
> und es dem Programmierer überlassen ob er es denn so stehen lassen will.

Die Warnung kannst du ja ganz leicht nachrüsten.
Einfach im Build-System zweimal kompilieren lassen, einmal mit -O0, 
einmal mit -Os,-O2,-O3...
Dann die ausgeworfen Binaries vergleichen. Falls unterschiedlich: 
"Warnung: Compiler hat optimiert!"

von Nop (Gast)


Lesenswert?

Zeno schrieb:
> Für ein i++
> sind nun mal eine bestimmte Anzahl von Taktschritten erforderlich

So funktioniert C ganz grundsätzlich nicht. Deswegen kann man das von 
einem C-Compiler auch nicht erwarten.

> Es könnte also
> durchaus sein, das sich der Programmierer was dabei gedacht hat

Dann hätte er "volatile" hinschreiben sollen. Wenn er das so wie W.S. 
nicht weiß, hätte er vorher C lernen sollen.

> insofern wäre es schon wünschenswert, wenn der Compiler das umsetzt was
> man hinschreibt

Nein. Nochmal, so funktioniert C nicht.

von Zeno (Gast)


Lesenswert?

Jörg W. schrieb:
> Wie Philipp schon schreibt: oft genug hat der Programmierer das nicht so
> direkt hingeschrieben, sondern es versteckt sich innerhalb von irgendwas
> anderem. Wenn du 'i = i * 2' schreibst, erwartest du ja auch nicht, dass
> dann der (bei Fehlen von Multiplikationsbefehlen in der CPU in einer
> Bibliothek sitzende) Code für eine Multiplikation mit 2 ausgeführt wird,
> wenn der Compiler eigentlich auch feststellen kann, dass er stattdessen
> viel einfacher nur ein Bit nach links schieben muss.
Jörg ich habe den Eindruck Du willst micht nicht verstehen und Dein 
Vergleich hinkt auch.
Mir ist es völlig wurscht wie der Compiler 'i = i * 2' umsetzt. Ob er 
dafür eine in der CPU evtl. vorhandene Multiplikationsinstruktion 
benutzt oder einfach nur ein Bit nach links schiebt ist mir in diesem 
Zusammenhang völlig egal. Ich erwarte schlichtweg das er den von mir 
hingeschriebenen Quelltext, solange er gültigen Code darstellt, in 
ausführbare Instruktionen für die CPU umsetzt, aber nicht entscheidet 
das der hingeschriebene Code eigentlich, nach seiner Ansicht, 
überflüssig ist und ihn deswegen einfach weg läßt. Der richtige Weg 
wäre, daß er mir in so einem Fall mitteilt das ich diese Codesequenz 
nochmals überdenken solle.
Compiler für andere Sprachen handhaben das anders und akzeptieren das 
was der Programmierer hin schreibt.
Ich merke aber schon, das ich hier gegen Windmühlen kämpfe und die 
Fangemeinde dieses Verhalten toll findet und lieber volatile 
hinschreibt, um dem Compiler zu sage, mache es so wie ich es 
hingeschrieben habe. So wird halt jeder auf seine Art glücklich. Mich 
piept so etwas an und genau deshalb meide ich C wo es nur geht, aber 
leider führt bei µC oftmals kein Weg daran vorbei.

Εrnst B. schrieb:
> Die Warnung kannst du ja ganz leicht nachrüsten.
> Einfach im Build-System zweimal kompilieren lassen, einmal mit -O0,
> einmal mit -Os,-O2,-O3...
> Dann die ausgeworfen Binaries vergleichen. Falls unterschiedlich:
> "Warnung: Compiler hat optimiert!"
Du hast ja nun mal gar nicht verstanden worum es mir geht - macht aber 
nichts.

von Εrnst B. (ernst)


Lesenswert?

Zeno schrieb:
> Du hast ja nun mal gar nicht verstanden worum es mir geht

Nach deinen zusätzlichen Ausführungen oben: Doch, das habe ich exakt 
verstanden. Ich hab mich nur darüber Lustig gemacht.

von Zeno (Gast)


Lesenswert?

Nop schrieb:
> So funktioniert C ganz grundsätzlich nicht. Deswegen kann man das von
> einem C-Compiler auch nicht erwarten.
> ...
Ja und genau deswegen fallen viele Anfänger erst mal so richtig auf die 
Fresse.

von Zeno (Gast)


Lesenswert?

Εrnst B. schrieb:
> Ich hab mich nur darüber Lustig gemacht.
Also wieder mal die typische Arroganz der eingefleischten 
C-Programmierer, die brauchen das ganz offensichtlich.

von Εrnst B. (ernst)


Lesenswert?

Zeno schrieb:
> Ja und genau deswegen fallen viele Anfänger erst mal so richtig auf die
> Fresse.

Nö. Die nehmen nämlich heutzutage Arduino, und da die 
fix-und-fertig-rundum-glücklich "delay()"-Funktion.
Irgendwelche Zeitvertrödelungs-Schleifen baut da keiner mehr selber.

von Nop (Gast)


Lesenswert?

Zeno schrieb:

> Ja und genau deswegen fallen viele Anfänger erst mal so richtig auf die
> Fresse.

Oh. Eine Programmiersprache muß man tatsächlich lernen. Unglaublich, das 
ist ja fast wie im richtigen Leben.

von Εrnst B. (ernst)


Lesenswert?

Zeno ist halt einfach ein paar Jahre zu früh dran.

Irgendwann, wenn die KI-Basierten Codegeneratoren ein Bewusstsein 
entwickelt haben und brauchbare Ergebnisse liefern, kann auch er seinen 
gedankenlesenden Do-What-I-Want Compiler haben.

von Nop (Gast)


Lesenswert?

Zeno schrieb:

> Ich merke aber schon, das ich hier gegen Windmühlen kämpfe und die
> Fangemeinde dieses Verhalten toll findet und lieber volatile
> hinschreibt

Ja, natürlich. Die Freiheit, die der Compiler ganz absichtlich hat, 
erlaubt ihm nämlich überhaupt erst etliche Optimierungen. Ob er die 
Variable im Register hält oder auf dem Stack etwa - und beides wird die 
Zeit so oder so erheblich beeinflussen. Genau dafür ist die as-if-Regel 
da. Ganz einfach.

Das hat nichts mit "lieber volatile hinschreiben" zu tun, sondern damit, 
daß auch Du auf einem ganz grundlegenden Level nicht verstehst, was C 
überhaupt ist.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Zeno schrieb:
> Ich erwarte schlichtweg das er den von mir hingeschriebenen Quelltext,
> solange er gültigen Code darstellt, in ausführbare Instruktionen für die
> CPU umsetzt, aber nicht entscheidet das der hingeschriebene Code
> eigentlich, nach seiner Ansicht, überflüssig ist und ihn deswegen
> einfach weg läßt

Dann darfst du ihn halt nicht optimieren lassen, -O0 als Option.

Dann macht er genau diese Tippeltappeltour und setzt alles 1:1 um. Das 
Resultat ist halt riesig groß und schweinelangsam, aber es entspricht 
dem, was du hingeschrieben hast.

Wenn du ihn dagegen optimieren lässt, dann sagst du ihm, dass er Dinge 
einfacher ausdrücken soll, als sie hingeschrieben worden sind. Wenn du 
nun einzelne Dinge doch nicht optimiert haben willst, musst du das dem 
Compiler mitteilen. "volatile" wurde schon genannt, ich hatte auf die 
Möglichkeit des Einstreuens von Inline-Assembler-Code (NOP) hingewiesen. 
Wie sinnvoll das dann ist, darüber lässt sich natürlich vortrefflich 
streiten, denn je nach CPU-Caching-Möglichkeiten kann das Resultat 
trotzdem noch rasend schnell abgearbeitet werden.

Aber so ein "do what I mean"-Compiler, also "optimiere überall außer da, 
wo ich mir gedacht (aber es nicht geschrieben) habe, dass du nicht 
optimieren sollst" muss wohl erst noch erfunden werden.

von Nop (Gast)


Lesenswert?

Jörg W. schrieb:

> Dann darfst du ihn halt nicht optimieren lassen, -O0 als Option.

Das ist allerdings Compiler-spezifisch, der C-Standard selber sieht 
derlei nicht vor. Prinzipiell dürfte ein C-Compiler also auch bei 
abgeschalteten Optimierungen solche Leerschleifen rauswerfen. Wenn der 
Code mit Optimierungen kaputt ist, dann ist es es nämlich auch ohne 
Optimierungen immer noch.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nop schrieb:
> Das ist allerdings Compiler-spezifisch, der C-Standard selber sieht
> derlei nicht vor.

Ist natürlich richtig, aber ist dir schon mal ein Compiler über den Weg 
gelaufen, der keine Möglichkeit hat, die Optimierungen abzuschalten? Ich 
vermute, dass man das während der Implementierung eines Compilers 
ohnehin benötigt.

von Εrnst B. (ernst)


Lesenswert?

Und auch der GCC unterlässt mit -O0 nicht alle Optimierungen

Sonst müsste am AVR eine Schleife
1
  while(true) PINB |= (1<<1);
eine andere Frequenz ausgeben als
1
  while(true) PINB |= (1<<7);
weil die Bitshifts am AVR unterschiedlich lange brauchen.

Aber der bösartige, verbrecherische Compiler setzt da trotz -O0 einfach 
eine vorberechnete Konstante ein, obwohl es anders in Quelltext steht!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

:-)

von Nop (Gast)


Lesenswert?

Jörg W. schrieb:
> aber ist dir schon mal ein Compiler über den Weg
> gelaufen, der keine Möglichkeit hat, die Optimierungen abzuschalten?

Nee, das nicht, aber wenn ich schon die Wahl habe, ob ich nach 
C-Standard programmiere oder mich auf ein bestimmtes Verhalten eines 
bestimmten Compilers verlasse, wähle ich Ersteres, weil Letzteres gerne 
später zu Problemen führt.

Etwa mit Portabilität oder auch nur einem schnöden Compiler-Update. Ich 
erinnere nur an die Story, wo GCC irgendwo bei 4.9 strict-aliasing zum 
Default gemacht hat und Torvalds sich aufgeregt hat, weil das Kernel 
Team erstens mit Pointer-Aliasing gearbeitet hatte sowie zweitens bei 
der Build-Chain geschlampt und das nicht explizit angewiesen hatte. Dann 
funktionierte es auf einmal nicht mehr.

Oder ganz typisch bei embedded: Mist, der Code paßt mit den neuen 
Features nicht mehr ins Flash, laß mal mit -Os die Größe reduzieren. 
Ooops, der auch vorher schon kaputte Code geht jetzt nicht mehr.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nop schrieb:
> laß mal mit -Os die Größe reduzieren.

Naja, wer im Embedded-Bereich nicht genau das von vornherein so macht, 
der tut mir leid. Nicht optimierter Code auf dem PC ist schon Mist, aber 
auf einem Controller ist es pure Geldverschwendung.

von Nop (Gast)


Lesenswert?

Jörg W. schrieb:

> Naja, wer im Embedded-Bereich nicht genau das von vornherein so macht,
> der tut mir leid.

Soviel also zum Thema "Optimierungen abschalten".

von Maxe (Gast)


Lesenswert?

Also ich versteh den Zeno schon irgendwie. Es gibt Optimierungen, für 
die man zumindest selber keine sinnvolle Anwendung sieht. Eine Schleife 
wegzuoptimieren würde für mich dazu gehören. Aber es kann natürlich 
sein, dass es die Anwendung doch gibt, Makros wurden hier ja schon 
angedeutet, auch Konstanten könnten in einer Schleife verrechnet werden, 
das dann der Compiler schon vollständig erledigen kann. Auch dass solche 
grenzwertigen Spezialfälle vom Compiler als solche erkannt werden 
müssten, was ein zusätzlicher Entwicklungsaufwand wäre, ist für mich ein 
nachvollziehbares Argument.

Philipp Klaus K. schrieb:
> An SDCC wird häufig kritisiert, dass es jede
> Funktion, die in einer Quellcodedatei steht, auch in die Binärdatei
> kompiliert [...], selbst wenn die betreffende
> Funktion gar nicht aufgerufen wird. Da geht es also nicht mal um ein
> einzelnes ++ oder eine leere Schleife, sondern um ganze Funktionen, von
> denen die Programmierer erwarten, dass der Compiler diese wegoptimiert!

Das versteh ich gut. Man versucht ja wiederverwendbaren Code zu 
schreiben bzw. versucht Code wiederzuverwenden und dazu gehört halt, 
dass man auch Funktionen hat, die man im aktuellen Projekt gerade nicht 
benötigt. Für Bibliotheken gilt das sowieso, auch wenn sie als Quellcode 
vorliegen.

von Εrnst B. (ernst)


Lesenswert?

Maxe schrieb:
> Eine Schleife
> wegzuoptimieren würde für mich dazu gehören.

Aber optimieren, dass sie schneller läuft, darf er?
d.H. die Schleife in ein einziges "NOP" zu reduzieren wäre OK, sie ganz 
wegzulassen ist nicht sinnvoll?

IAW: Wäre es für dich OK, wenn der Compiler aus
1
 int sum=0;
2
 for (int i=0;i<10;i++) sum+=i;
ein
1
 int sum=45;
macht?

Oder ist das nicht sinnvoll?
Oder macht es dir Angst, dass der Compiler diese Optimierungsmöglichkeit 
gesehen hat?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nop schrieb:
> Soviel also zum Thema "Optimierungen abschalten".

Naja, du warst doch derjenige, der unbedingt eine 1:1-Umsetzung haben 
will.

Die geht, wenn man die Optimierung ausschaltet.

Ich bin nur derjenige, der sagt, dass ich das im Embedded-Bereich 
nicht sinnvoll finde.

von Nop (Gast)


Lesenswert?

Jörg W. schrieb:

> Naja, du warst doch derjenige, der unbedingt eine 1:1-Umsetzung haben
> will.

Äh, nein? Das waren Zeno und W.S., während ich derjenige war, der sich 
lieber an den C-Standard hält. Und Dein Vorschlag war es doch, mit -O0 
die Optimierungen auszuschalten:

> Dann darfst du ihn halt nicht optimieren lassen, -O0 als Option.

Aber wenn man sich nicht an den C-Standard hält, meckert man, daß die 
Optimierungen den Code kaputtmachen, obwohl er selbstverständlich schon 
vorher kaputt war. Wenn man daher ohne Optimierungen arbeitet, anstatt 
den Code zu fixen, dann rennt man später im Projekt u.U. genau in die 
von mir beschriebene Situation: Code ist zu groß, und mit -Os geht er 
nicht mehr.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nop schrieb:
>> Naja, du warst doch derjenige, der unbedingt eine 1:1-Umsetzung haben
>> will.
>
> Äh, nein?

Oh, 'tschuldigung, stimmt.

von c-hater (Gast)


Lesenswert?

Jörg W. schrieb:

> GCC hatte früher für diesen Konstrukt tatsächlich eine "Sonderlocke"
> implementiert, aber das war zusätzlicher Aufwand, just diese Situation
> ("toter Code, der stehen bleiben soll") zu erkennen, und irgendwann
> haben sie halt diese Sonderlocke abgeschafft.

Tja, aber in der typisch inkonsequenten Weise der C-"Logik" natürlich 
nicht sehr konsequent.

Denn, in:
1
int main(void) {
2
3
  while (1) {
4
    //nothing
5
  }
6
}

wird die Schleife trotz ihrer offensichtlichen Nutzlosigkeit NICHT 
wegoptimiert. Nach der von dir beschriebenen "superlogischen Logik", die 
so typisch für dieses unsäglich erbärmliche C-Gefrickel ist, hätte sie 
aber wegoptimiert werden müssen! Denn klarerweise geschieht im Body 
nichts nützliches, d.h.: auch die diesen Body umfassende 
Kontrollstruktur ist unnütz, denn eine Schleife, die unendlich garnix 
macht, macht am Ende garnix.

Tja, so ist das mit der Logik...

von Nop (Gast)


Lesenswert?

c-hater schrieb:
> hätte sie aber wegoptimiert werden müssen!

Nope. Ohne Endlosschleife gibt's nämlich einen beobachtbaren externen 
Effekt: Das Programm endet. Bei den Delay-Schleifen gibt's so einen 
Unterschied nicht. Erst denken, dann ranten.

von c-hater (Gast)


Lesenswert?

Nop schrieb:

> Nope. Ohne Endlosschleife gibt's nämlich einen beobachtbaren externen
> Effekt: Das Programm endet. Bei den Delay-Schleifen gibt's so einen
> Unterschied nicht. Erst denken, dann ranten.

Nur ist das Problem: an jeder anderen Stelle im Programm wird EXAKT 
dieselbe Schleife wegoptimiert.

Was ist denn das für ein Sprachstandard? Einmal hüh, einmal hott bei 
EXAKT demselben Sprachkonstrukt?

Das ist lächerlich für einen Sprachstandard!

von Joerg W. (joergwolfram)


Lesenswert?

> Nur ist das Problem: an jeder anderen Stelle im Programm wird EXAKT
> dieselbe Schleife wegoptimiert.

seit wann das? Alles was nach
1
while(1){};
kommt, kann natürlich wegoptimiert werden (non-reachable code).

Jörg

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Joerg W. schrieb:
> seit wann das?

Warum sollte jemand, der sich "c-hater" nennt, sich mit C auskennen 
(geschweige denn mit dessen Standard)?

von Michael F. (Firma: IAR Systems) (michael_iar)


Lesenswert?

Jörg W. schrieb:
> Naja, du warst doch derjenige, der unbedingt eine 1:1-Umsetzung haben
> will.
>
> Die geht, wenn man die Optimierung ausschaltet.

Moin,

bist Du sicher, dass der von Dir verwendete Compiler bei -O0 wirklich 
den kompletten Code 1:1 übersetzt?

z.B. der C/C++ Development Guide zum IAR Compiler für Arm v9.30.1 sagt 
auf Seite 250 zu den Optimierungen:
1
None (Best debug support)
2
- Variables live through their entire scope
3
- Dead code elimination
4
- Redundant label elimination
5
- Redundant branch elimination

Also wird bereits bei "Optimization = none" bis zu einem gewissen Punkt 
nur das übersetzt, was am Ende auch Sinn macht und nach meinem 
Verständnis sollte das vom C Standard (z.B. C99 - 5.1.2.3) abgedeckt 
sein.

z.B. wird für das Incrementieren von foo kein Code mehr erzeugt, da die 
Instruktion "unreachable" ist (aber es wird zumindest eine entsprechende 
Warnung angezeigt):
1
int main(void)
2
{
3
   int foo = 123;
4
   
5
   while (1){};
6
   
7
   foo++;
8
}

@ Philipp:
Wie handhabt das denn der SDCC?

Gruß,
Michael

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Michael F. schrieb:
> bist Du sicher, dass der von Dir verwendete Compiler bei -O0 wirklich
> den kompletten Code 1:1 übersetzt?

Naja, es wurde ja weiter oben schon angemerkt, dass insbesondere die 
Konstantenberechnung trotzdem noch zur Compilezeit erfolgt. Bei dead 
code elimination wäre ich mir jetzt nicht ganz so sicher, ich glaube, 
die macht ein GCC (und vermutlich auch Clang) nur mit Optimierungsniveau 
größer 0, da bei -O0 keinerlei Codeflussanalyse vorgenommen wird.

Übrigens sollte man dort zumindest schon aus diesem Grunde mit mehr als 
-O0 arbeiten, denn eine ganze Reihe von Warnungen können sonst gar nicht 
generiert werden …

Klar, der C-Standard äußert sich nicht zu Optimierungen, die sind da 
"out of scope", da gilt die "as if"-Regel.

von Martin H. (horo)


Lesenswert?

Michael F. (Firma: IAR Systems) schrieb:
> Wie handhabt das denn der SDCC?

Dürft Ihr bei IAR keinen SDCC benutzen? :)
1
void main(void)
2
{
3
    int foo = 123;
4
    while (1){};
5
    foo++;
6
}

Übersetzt in ASM code mit ...
1
sdcc -mmcs51 -S dc.c
2
dc.c:5: warning 126: unreachable code
3
dc.c:5: warning 126: unreachable code
4
dc.c:5: warning 126: unreachable code

... ergibt dann in dc.asm:
1
...
2
;--------------------------------------------------------
3
        .area CSEG    (CODE)
4
;------------------------------------------------------------
5
;Allocation info for local variables in function 'main'
6
;------------------------------------------------------------
7
;foo                       Allocated to registers 
8
;------------------------------------------------------------
9
;       dc.c:1: void main(void)
10
;       -----------------------------------------
11
;        function main
12
;       -----------------------------------------
13
_main:
14
        ar7 = 0x07
15
        ar6 = 0x06
16
        ar5 = 0x05
17
        ar4 = 0x04
18
        ar3 = 0x03
19
        ar2 = 0x02
20
        ar1 = 0x01
21
        ar0 = 0x00
22
;       dc.c:5: while (1){};
23
00102$:
24
;       dc.c:7: foo++;
25
;       dc.c:8: }
26
        sjmp    00102$
27
        .area CSEG    (CODE)
28
        .area CONST   (CODE)
29
        .area XINIT   (CODE)
30
        .area CABS    (ABS,CODE)

Für Z80 ist das Ergebnis ähnlich, 18 FE
1
   0000                      47 _main::
2
                             48 ;dc.c:4: while (1){};
3
   0000                      49 00102$:
4
                             50 ;dc.c:5: foo++;
5
                             51 ;dc.c:6: }
6
   0000 18 FE         [12]   52         jr      00102$
7
                             53         .area _CODE
8
                             54         .area _INITIALIZER
9
                             55         .area _CABS (ABS)

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Joerg W. schrieb:

> seit wann das?

Keine Ahnung.

> Alles was nach
>
1
> while(1){};
2
>
> kommt, kann natürlich wegoptimiert werden (non-reachable code).

Ja, das ist ja auch logisch und somit sinnvoll. Keine Einwände 
meinerseits.

Ich meine sowas (absichtlich eingebauter "trap"):
1
if (errordetected) {
2
  while (true) {
3
    //nothing here: endless loop is INTENDED (as trap)
4
  }
5
} else {
6
  //perform the normal behaviour
7
}

Was tatsächlich rauskommt, ist aber, dass die gewollte Endlosschleife 
ersatzlos rausoptimiert wird und statt dessen unmittelbar der Code 
hinter dem Else-Zweig der Verzweigung ausgeführt wird.

Ist allerdings errordetected != true, wird erwartungsgemäß der "normal 
behavior" durchlaufen (und macht auch, was er soll) und erst dann der 
Code hinter der Verzweigung.

von Zeno (Gast)


Lesenswert?

Εrnst B. schrieb:
> Irgendwann, wenn die KI-Basierten Codegeneratoren ein Bewusstsein
> entwickelt haben und brauchbare Ergebnisse liefern, kann auch er seinen
> gedankenlesenden Do-What-I-Want Compiler haben.
Wieso muß der Compiler GEdanken lesen? Der soll nur machen was ich ihm 
auf den "Einkaufszettel" schreibe.
Im Übrigen gibt es einen solchen Compiler schon seit ca. 1971. Der tut 
das was ich ihm hin schreibe - ist halt kein C.

von Zeno (Gast)


Lesenswert?

Jörg W. schrieb:
> Warum sollte jemand, der sich "c-hater" nennt, sich mit C auskennen
> (geschweige denn mit dessen Standard)?
Ich befürchte mal das sich der c-heater mit C besser auskennt als Du 
denkst und nur durch die Besonderheiten diese Sprache zum c-hater 
geworden ist.

Michael F. schrieb:
> z.B. wird für das Incrementieren von foo kein Code mehr erzeugt, da die
> Instruktion "unreachable" ist (aber es wird zumindest eine entsprechende
> Warnung angezeigt):
So wäre das ja auch für mich in Ordnung - mit der Warnung, weil dann 
entscheide ich ob an dieser Stelle "optimiert" wird oder nicht.

von Nop (Gast)


Lesenswert?

c-hater schrieb:

> Was tatsächlich rauskommt, ist aber, dass die gewollte Endlosschleife
> ersatzlos rausoptimiert wird und statt dessen unmittelbar der Code
> hinter dem Else-Zweig der Verzweigung ausgeführt wird.

Ist das so? Gerade mal auf Godbolt geguckt für ARM-GCC 12.1 mit -O3. 
Dieser Codeschnipsel hier...
1
volatile int dummy;
2
3
void func(int errordetected)
4
{
5
    if (errordetected) {
6
        while (true) {
7
            //nothing here: endless loop is INTENDED (as trap)
8
        }
9
    } else {
10
        dummy++;
11
    }
12
}

... wird compiliert zu:
1
func(int):
2
        cbnz    r0, .L3
3
        movw    r3, #:lower16:.LANCHOR0
4
        movt    r3, #:upper16:.LANCHOR0
5
        ldr     r2, [r3]
6
        adds    r2, r2, #1
7
        str     r2, [r3]
8
        bx      lr
9
.L3:
10
        b       .L3
11
dummy:

Es wird also die Endlosschleife ausgeführt, wenn errordetected ungleich 
0 ist, und sonst die Dummy-Variable erhöht.

von Nop (Gast)


Lesenswert?

Ich vermute daher, daß in was auch immer Dein Beispiel ursprünglich 
getan hat, der Fall des errordetected deswegen gar nicht auftreten kann, 
weil Du dann undefined behaviour eingebaut hättest und der Compiler das 
erkannt hat. Dann darf der Compiler diesen Fall behandeln, wie immer er 
das möchte.

Das ist ein Fehler im Code, wenngleich C99 knapp 200 Fälle von undefined 
behaviour hat und man das zurecht kritisieren kann, insbesondere weil 
man nicht immer eine Warnung dazu bekommt. In dieser Hinsicht macht Rust 
es besser.

von Zeno (Gast)


Lesenswert?

c-hater schrieb:
> Was ist denn das für ein Sprachstandard? Einmal hüh, einmal hott bei
> EXAKT demselben Sprachkonstrukt?
Naja für die main() braucht man halt ab und an mal ne Endlosschleife um 
goto zu vermeiden. Obwohl dafür gäbe es ja auch for(;;){} - ist genau so 
hirnrissig.

von Nop (Gast)


Lesenswert?

Zeno schrieb:
> Obwohl dafür gäbe es ja auch for(;;){} - ist genau so hirnrissig.

Nein, ist es nicht. Es ist deswegen die von K&R propagierte und die 
einzige von Lint akzeptierte Form, weil man bei einer while-Schleife die 
Schleifenbedingung aus Versehen auf endlos stellen kann, besonders im 
Zusammenspiel mit Macro-Defines. Bei der Form mit for(;;){} gibt's 
dieses Risiko nicht.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Zeno schrieb:
> Ich befürchte mal das sich der c-heater mit C besser auskennt als Du
> denkst

Diesen Eindruck hat er bei mir im Laufe der Zeit keineswegs 
hinterlassen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nop schrieb:
> Es wird also die Endlosschleife ausgeführt, wenn errordetected ungleich
> 0 ist, und sonst die Dummy-Variable erhöht.

Zumal es derartige Endlosschleifen auch sonst immer mal gibt, 
beispielsweise die default-Handler für allerlei Exceptions beim ARM sind 
typischerweise genau sowas. Und die werden natürlich von keinem Compiler 
weg optimiert.

Hier aus dem Atmel-ARM-Sourcecode:
1
/**
2
 * \brief Default interrupt handler for unused IRQs.
3
 */
4
void Dummy_Handler(void)
5
{
6
        while (1) {
7
        }
8
}

von Zeno (Gast)


Lesenswert?

Jörg W. schrieb:
> Diesen Eindruck hat er bei mir im Laufe der Zeit keineswegs
> hinterlassen.
Der Eindruck kann manchmal auch täuschen.

Nop schrieb:
> Zeno schrieb:
>> Obwohl dafür gäbe es ja auch for(;;){} - ist genau so hirnrissig.
>
> Nein, ist es nicht. Es ist deswegen die von K&R propagierte und die
> einzige von Lint akzeptierte Form, weil man bei einer while-Schleife die
> Schleifenbedingung aus Versehen auf endlos stellen kann, besonders im
> Zusammenspiel mit Macro-Defines. Bei der Form mit for(;;){} gibt's
> dieses Risiko nicht.
Ja logo finden die Fans der Sprache C so was geil, weil so etwas ohne 
jegliche Logik ist, man muß es halt auswendig lernen.
Man kann jede Schleife zu einer Endlosschleife machen, wenn man die 
Abbruchbedingung entsprechend setzt. Ob das wissentlich, versehentlich 
oder gar gewollt gemacht wird ist dabei völlig Rille.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Zeno schrieb:
> Man kann jede Schleife zu einer Endlosschleife machen, wenn man die
> Abbruchbedingung entsprechend setzt.

Klar kannst du das.

Hier geht es ausschließlich darum, 1) welche Gepflogenheiten es (aus was 
auch immer für Gründen) schon gibt und 2) was entsprechende 
Syntaxchecker vorzugsweise erwarten. (Beides hängt natürlich zusammen.) 
Das ist halt die "for (;;)"-Form, da sie praktisch nie versehentlich 
"entstehen" kann.

Der eher seltene Fall einer Endlosschleife *) ist es gewiss nicht wert, 
dass man ihm nun einen eigenen Sprachkonstrukt widmet – das wäre ja die 
"offizielle" Alternative.

*) Im Kontext einer HDL sieht das anders aus, aber wir reden hier über 
Programmiersprachen.

von Gcc (Gast)


Lesenswert?

So ein Compiler kann schon unterscheiden zwischen einer Endlosschleife 
und einer Schleife die nur eine (vermutlich danach nicht mehr 
verwendete) Variable hochzählt. Ersteres soll nie enden, das letztere 
soll so schnell wie möglich ausgeführt werden, als am besten mit 0 
Takten. Und es gibt eine (indirekte) Möglichkeit dem Compiler zu sagen, 
daß man den Zählvorgang doch haben will, vermutlich weil man Zeit 
verbrennen will.
Wo ist also das Problem. Wer diese Sprache nicht mag, der soll es 
einfach lassen. So wie ich die Sprache Baujahr 1971 nicht (mehr) 
benutze, das aber normalerweise jedem verheimliche. Auch Fe2O3 brauch 
ich nicht, aber auch das will ich niemandem erklären.

von Zeno (Gast)


Lesenswert?

Gcc schrieb:
> Wo ist also das Problem. Wer diese Sprache nicht mag, der soll es
> einfach lassen. So wie ich die Sprache Baujahr 1971 nicht (mehr)
> benutze
Genauso ist es, jeder soll auf seine Art glücklich werden.

Gcc schrieb:
> das aber normalerweise jedem verheimliche
Warum das? Muß man sich rechtfertigen wenn man diese Sprache nicht mag?

von W.S. (Gast)


Lesenswert?

Jörg W. schrieb:
> Hier geht es ausschließlich darum, 1) welche Gepflogenheiten es (aus was
> auch immer für Gründen) schon gibt und 2) was entsprechende
> Syntaxchecker vorzugsweise erwarten. (Beides hängt natürlich zusammen.)
> Das ist halt die "for (;;)"-Form, da sie praktisch nie versehentlich
> "entstehen" kann.

Nun ja, Gepflogenheiten sind etwas, das nicht aus rationaler Überlegung 
entsteht, sondern eben nur aus 'das mache ich nach'. So wie bei 
Hobby-Tischlern, daß sie ihren Hobel NIE gerade auf ihren Basteltisch 
stellen, sondern immer nur auf die Seite legen. Irrational? Ja. Eben wie 
alle Gepflogenheiten. Aber herzlich egal.

Allerdings sieht das bei solchen Konstrukten wie for(;;) aus logischer 
Sicht anders aus, als du es darstellst. Von einem Sprachkonstrukt 
erwartet man eigentlich, daß es zu einem bestimmten Zweck existiert. So 
ist der eigentliche Zweck von 'for' eben, eine abgezählte Schleife zu 
machen und der von 'while' eine unabgezählte Schleife, aber mit einer 
Abbruchbedingung. So etwas zu korrumpieren, indem man die Abzählung oder 
die Abbruchbedingung hintertreibt, wird in C zwar nicht als 
Programmierfehler gewertet, führt aber dennoch zu einer entarteten 
Schleife, der ein wesentlicher Teil fehlt. Es ist unlogisch, ein 
Sprachkonstrukt zu verwenden, dessen Zweck man garnicht bezweckt. Da 
können K&R dazu sagen, was sie wollen. Was da bleibt ist eben nur die 
Gepflogenheit. Und die ist irrational. Genauso wie der Streit darum, an 
welchem Ende man das Ei aufschlägt.

W.S.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

W.S. schrieb:
> Allerdings sieht das bei solchen Konstrukten wie for(;;) aus logischer
> Sicht anders aus, als du es darstellst.

Du hast nur eine Seite meiner Darstellung einbezogen – die andere Seite, 
dass eine "for(;;)"-Schleife halt niemals "aus Versehen" (auch nicht 
durch irgendwelche Makroerweiterungen etc.) entsteht, hast du ignoriert. 
Diese dürfte aber wesentlich dazu beigetragen haben, dass diese 
Gepflogenheit halt überhaupt so entstanden ist und dass sich 
Syntaxchecker (wie Lint) daran orientiert haben, eine solche Schleife 
nicht als potenziellen Programmierfehler zu warnen.

Kommt natürlich noch dazu, dass Endlosschleifen außerhalb von "deep 
embedded" nur sehr selten benutzt werden. Es ist also mittelmäßig müßig, 
sich nun ausgerechnet an solch einem Detail hier aufzugeilen. Es gibt 
Dinge in C, die in die Kategorie "historisch gewachsen aber praktisch 
nicht mehr zu ändern" fallen, die viel wesentlicher wären, 
beispielsweise dass die Sichtbarkeit einer nicht näher auf Toplevel 
einer Übersetzungseinheit bezeichneten Variablen oder Funktion global 
statt modulintern ist. Aus heutiger Sicht hätte man das lieber anders 
herum gehabt, also explizite Deklaration all dessen, was über den Modul 
hinaus geht.

von Gcc (Gast)


Lesenswert?

Zeno schrieb:
> Gcc schrieb:
>> das aber normalerweise jedem verheimliche
> Warum das? Muß man sich rechtfertigen wenn man diese Sprache nicht mag?

Was hat das mit Rechtfertigung zu tun, wenn man nicht jedem seine 
eigenen Vorlieben andienen will.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

W.S. schrieb:
> So ist der eigentliche Zweck von 'for' eben, eine abgezählte Schleife zu
> machen

Nö. Eine Zählung mittels i++ in einer for-Schleife ist lediglich ein 
Spezialfall einer Anwendung von einer for-Schleife. Das Konstrukt 
"for" in C ist aber wesentlich allgemeiner gefasst. Die Verwendung einer 
Zählvariablen in einer for-Schleife wird zwar der meiste Anwendungsfall 
sein (weil es so am bequemsten ist), trotzdem ist dieses nicht der 
"eigentliche Zweck".

Nur ein Gegenbeispiel von tausenden:
1
  for (ptr = obj->start; *ptr; ptr = obj->next)

Wir sprechen hier nicht über Basic oder Pascal, wo eine for-Schleife 
tatsächlich explizit bzw. implizit über eine Zählvariable läuft. Und ich 
halte es auch für einen Fehler, Eigenschaften von anderen 
Programmiersprachen auf C zu projizieren zu wollen. Das führt nur zu 
einer Einschränkung - nämlich seines eigenen Denkapparates.

: Bearbeitet durch Moderator
von Martin H. (horo)


Lesenswert?

Frank M. schrieb:
> Nur ein Gegenbeispiel von tausenden:
> for (ptr = obj->start; *ptr; ptr = obj->next)

Besser so?
1
for (ptr = obj->start; ptr && *ptr; ptr = ptr->next)

von DerEgon (Gast)


Lesenswert?

Martin H. schrieb:
> Besser so?

Sehe ich auch so. Besser.

von DPA (Gast)


Lesenswert?

Martin H. schrieb:
> for (ptr = obj->start; ptr && *ptr; ptr = ptr->next)

Nicht eher so?

for (ptr = obj->start; ptr; ptr = ptr->next)

von DPA (Gast)


Lesenswert?

Wobei, ich habe auch schon diese Variante gesehen:
1
for (ptr = &obj->start; *ptr; ptr = &(*ptr)->next)
2
  if(*ptr == needle)
3
    break;
4
if(*ptr){
5
  void* x=*ptr;
6
  *ptr = x->next;
7
  free(x);
8
}

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Martin H. schrieb:
> Besser so?
> for (ptr = obj->start; ptr && *ptr; ptr = ptr->next)

Sorry, ja, natürlich, wobei ich ptr alleine meinte - ohne Sternchen und 
auch ohne die 2. Bedingung. Letztere kommt meist auf den Kontext an. :-)

: Bearbeitet durch Moderator
von B. P. (skorpionx)


Lesenswert?

Meine Antwort:
Beitrag "microchip c18 vs. sdcc"
Ich war noch zufrieden. Dann habe ich für meine Anwendungen einen
Interpreter entwickeln  um möglich schnell zu Lösungen zu kommen.
Im Interpreter sind Menüs im Rom beschrieben. Und dann kam zum
Einsicht dieser Fehler:
https://sourceforge.net/p/sdcc/bugs/2589/
Zur Zeit keine Lösung. Trotzdem arbeite ich weiter mit SDCC.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.