Hallo, in C hat ja static eine doppelbedeutung. -bei lokalen variablen innerhalb von funktionsrümpfen wird eine variable statisch im speicher abgelegt und bleibt somit auch nach dem funktionsaufruf erhalten. hier hat "static" die bedeutung von "feststehend" -bei funktionen/variablen wird mit static die sichtbarkeit auf die aktuelle übersetzungseinheit der funktion/variable beschränkt. warum zum teufel haben die macher von C hier auch das schlüsselwort static=feststehend verwendet???? das macht doch gar keinen sinn und führt zu verwirrung bei dieser doppelverwendung? oder findet irgendwas im hintergrund statt, das die bedeutung von static an dieser stelle erklärt?? mfg
Gast
#3603181
Sina stellte fest:
>..und führt zu verwirrung bei dieser doppelverwendung
Die Syntax dieser Sprache führt ohnehin oft zu Verwirrung und ist schwer
zu erlernen. Da kommt es auf diese Doppeldeutigkeit auch nicht mehr an.
Gast
#3603189
Kernziel und Sinn dieser Sprache ist maximale Verwirrung fuer minimale Produktivitaet. Motto : wie kann man einen Job in die Laenge ziehen.
Return of Schnulli schrieb: > Die Syntax dieser Sprache führt ohnehin oft zu Verwirrung und ist schwer > zu erlernen. Da kommt es auf diese Doppeldeutigkeit auch nicht mehr an. Man stelle sich vor, es gibt Programmiersprachen, da hat sogar schon ein simples Gleichheitszeichen eine mehrfache Bedeutung, die sich nur aus dem Kontext erschließt... Mit B=3 ist je nach Positionierung etwas anderes als B=3 gemeint:
1 | |
2 | |
3 | |
Gast
#3603197
> das macht doch gar keinen sinn und > führt zu verwirrung bei dieser doppelverwendung? Wir C-Programmier wollen halt nicht das sich jeder Schnullerbubi Programmierer schimpfen kann. :-) Olaf
Gast
#3603198
ist doch ganz einfach - man muss weniger Schlüsselworte lernen. auch die Buchstaben haben in C oft eine mehrfache Verwendung: "i" wird in if und while verwendet.
Gast
#3603206
Im Kern ist das static in beiden Fällen die Ansage, dass der Compiler direkt eine feste Adresse benutzen soll. Bei einer Funktion hat das dann die Folge, das der Linker die Funktion nicht mehr bearbeitet und externe die nicht nutzen können. Für eine Variable ist der Nebeneffekt halt dass der Wert erhalten bleibt. Das kommt hat weil C eine alte Hardware nahe Sprache ist, mehr von der ASM Seite gewachsen als als Hochsprache geplant.
wem das nicht reicht, dem empfehle ich die Sprache Brainfu*ck
ahhh.... super, genau das wollte ich wissen... daaanke lg
Es gibt schlimmere Doppelbelegungen. Z.B. wenn man eine Schleife verlassen will, geht das mit Break. Hat man mehrere Abbruchbedingungen, würde sich ein Switch geradezu anbieten und wäre auch am besten lesbar. Dummm nur, daß dann das Break nicht die Schleife verläßt. Hier kann man nur ein Goto zum Verlassen benutzen.
... dann gibt es noch die Variante in C++, hier haben alle Instanzen Zugriff auf die gleiche static variable innerhalb einer member-funktion :-)
sina anargo schrieb: > warum zum teufel haben die macher von C hier auch das schlüsselwort > static=feststehend verwendet? Warum zum Teufel ist „modul-lokal“ nicht die voreingestellte Sichtbarkeitsregel? Dann hätte man “global” als Schlüsselwort für solche Daten und Funktionen festlegen können, die auch außerhalb der aktuellen Übersetzungseinheit sichtbar sein müssen. Die Antwort ist ganz einfach: historischer Ballast.
@dl8dtl modul-lokal in einer Sprache in der Module allenfalls als Toolchain-Konzept aber nicht wirklich als Sprachkonstrukt vorkommen? Klingt riskant...
Verminderung der Namensraumverschmutzung. Jedes der Schluesselworte faellt aus der Menge der moeglichen Bezeichner heraus -> nicht gut.
sina anargo schrieb: > in C hat ja static eine doppelbedeutung. Das sieht nur auf den ersten Blick so aus. Beide Deiner Beschreibungen passen sowohl bei lokalen als auch bei globalen: 1. Beide Variablen-Typen sind "feststehend", liegen also nicht auf dem Stack oder Heap. 2. Beide Typen sind "von außen" nicht sichtbar. Da ist also gar keine Doppelbedeutung, wenn man etwas länger drüber nachdenkt.
Gast
#3603265
kauft Euch ein C-Buch!
Gast
#3603485
Peter Dannegger schrieb: > Dummm nur, daß dann das Break nicht die Schleife verläßt. > Hier kann man nur ein Goto zum Verlassen benutzen. Oder einfach 'continue' ?
Gast
#3603494
Continue verlässt die Schleife aber nicht, sondern führt die nächste Iteration aus
Gast
#3603504
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
Alles nur kein GOTO :P
Andy D. schrieb: > @dl8dtl modul-lokal in einer Sprache in der Module allenfalls als > Toolchain-Konzept aber nicht wirklich als Sprachkonstrukt vorkommen? > Klingt riskant... hä? In C heißt das eben anders, z.b. "internal linkage" und "translation unit" etc. Siehe 6.2.2 Linkages of Identifiers.
Mike Roh schrieb: >
1 | |
2 | |
3 | |
4 | |
5 | |
> > Alles nur kein GOTO :P Peter meinte eine Schleife mit echter Abbruchbedingung - darin ein switch. Man kann die Schleife innerhalb des Switches entweder mit einem goto verlassen oder ... so mache ich das meist ... vor dem break dafür sorgen, dass die Bedingung der Schleife nicht mehr erfüllt ist. Gruß, Frank
Ulrich schrieb: > Im Kern ist das static in beiden Fällen die Ansage, dass der Compiler > direkt eine feste Adresse benutzen soll. Bei einer Funktion hat das dann > die Folge, das der Linker die Funktion nicht mehr bearbeitet und ... Käse :-) Der Compiler hat mit Adressvergabe grad garnix am Hat, das macht immer noch der Linker / Lokator, im Fall der GCC also ld.
Gast
#3603534
Random ... schrieb: > ... dann gibt es noch die Variante in C++, hier haben alle Instanzen > Zugriff auf die gleiche static variable innerhalb einer > member-funktion :-) Und dann gibt's auch noch Member-Funktionen, die static sind. Frank M. schrieb: > sina anargo schrieb: >> in C hat ja static eine doppelbedeutung. > > Das sieht nur auf den ersten Blick so aus. Beide Deiner Beschreibungen > passen sowohl bei lokalen als auch bei globalen: > > 1. Beide Variablen-Typen sind "feststehend", liegen also nicht auf dem > Stack oder Heap. Das tut eine Variable außerhalb der Funktion auch ohne static. > 2. Beide Typen sind "von außen" nicht sichtbar. Das ist bei lokalen Variablen aber immer so und kommt ebenfalls nicht erst durch static. > Da ist also gar keine Doppelbedeutung, wenn man etwas länger drüber > nachdenkt. Und wenn man noch etwas länger drüber nachdenkt, ist doch eine da. ;-)
Gast
#3603545
Johann L. schrieb: > Ulrich schrieb: >> Im Kern ist das static in beiden Fällen die Ansage, dass der Compiler >> direkt eine feste Adresse benutzen soll. Bei einer Funktion hat das dann >> die Folge, das der Linker die Funktion nicht mehr bearbeitet und ... > > Käse :-) Der Compiler hat mit Adressvergabe grad garnix am Hat, das > macht immer noch der Linker / Lokator, im Fall der GCC also ld. Das ist nicht ganz richtig. Der Compiler könnte static Funktionen z.b. inlinen.
Rolf Magnus schrieb: >> Da ist also gar keine Doppelbedeutung, wenn man etwas länger drüber >> nachdenkt. > > Und wenn man noch etwas länger drüber nachdenkt, ist doch eine da. ;-) Welche denn? Die beiden im Ausgangsposting genannten jedenfalls nicht. Denn diese treffen für beide Typen von static-Variablen zu. Auch Deine (natürlich korrekte) Aussage > Das tut eine Variable außerhalb der Funktion auch ohne static. ist für mich kein wirklicher Widerspruch.
Mike Roh schrieb: > Johann L. schrieb: >> Ulrich schrieb: >>> Im Kern ist das static in beiden Fällen die Ansage, dass der Compiler >>> direkt eine feste Adresse benutzen soll. Bei einer Funktion hat das dann >>> die Folge, das der Linker die Funktion nicht mehr bearbeitet und ... >> >> Käse :-) Der Compiler hat mit Adressvergabe grad garnix am Hat, das >> macht immer noch der Linker / Lokator, im Fall der GCC also ld. > > Das ist nicht ganz richtig. Der Compiler könnte static Funktionen z.b. > inlinen. Was aber nix mit Adressvergabe zu tun hat, sondern damit, ob er die Implementierung der Funktion kennt oder nicht. Er kann auch extern Funktionen inlinen, etwa mit Optimierungen wie LTO. Auch das hat im Kern nix mit Adressvergabe zu tun. Der Compiler vergibt keine Adressen.
Im Ur-C-Compiler für Unix war der "static"-Qualifier lokalen Variablen vorbehalten, wo er festlegt, dass die Lebensdauer einer Variable im Gegensatz zu "auto" nicht auf die Dauer der Funktionsausführung beschränkt sein soll. Globale Variablen mit "static" gab es nicht, was ja auch logisch ist, da globale Variablen in C immer statisch sind. Es entstand neben dem Unix-C-Compiler noch einer für GCOS, der bereits die spezielle Bedeutung von "static" für globale Variablen implementiert hatte. Dass für dieses Feature ein bereits vorhandenes Schlüsselwort genutzt wurde, hatte den Vorteil, dass der GCOS-Compiler (zumindest in dieser Punkt) abwärtskompatibel zum Unix-Compiler war. Später wurde dieses Feature dann auch in den Unix-Compiler übernommen, zusammen mit der Möglichkeit, statische lokale Veriablen initialisieren zu können, was vorher mit dem Unix-Compiler ebenfalls nicht möglich war.
Noch ne Doppelfunktion:
1 | |
2 | |
3 | |
Einmal Adresse 5 und einmal Wert 6.
Andy D. schrieb: > modul-lokal in einer Sprache in der Module allenfalls als > Toolchain-Konzept aber nicht wirklich als Sprachkonstrukt vorkommen? Dann nenne es „lokal zur Übersetzungseinheit“, wenn dir das Wort besser als „Modul“ gefällt. Yalu X. schrieb: > Es entstand neben dem Unix-C-Compiler noch einer für GCOS, der bereits > die spezielle Bedeutung von "static" für globale Variablen implementiert > hatte. Sag ich doch, historischer Ballast. :-)
Return of Schnulli schrieb: > Sina stellte fest: >>..und führt zu verwirrung bei dieser doppelverwendung > > Die Syntax dieser Sprache führt ohnehin oft zu Verwirrung und ist schwer > zu erlernen. Da kommt es auf diese Doppeldeutigkeit auch nicht mehr an. Ja eine gewisse Barriere gibt es schon um C zu lernen. Wenn man weiss was man erreichen will, gibts auch keine Verwirrung. Must du halt lernen wie es verwendet wirdt.
Mike Roh schrieb: >
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
> > Alles nur kein GOTO :P wieso denn nicht? Ich finde GOTO gut. Wird ja ohnehin in ein GOTO (JMP) uebersetzt auf assemblerebene. ein seitenlanges switch statement mit breaks ist auch unuebersichtlich. In Turbo Basic war SELECT CASE ein richtiges Schnuerkorsett.
Peter Dannegger schrieb: > Es gibt schlimmere Doppelbelegungen. > > Z.B. wenn man eine Schleife verlassen will, geht das mit Break. > Hat man mehrere Abbruchbedingungen, würde sich ein Switch geradezu > anbieten und wäre auch am besten lesbar. > Dummm nur, daß dann das Break nicht die Schleife verläßt. > Hier kann man nur ein Goto zum Verlassen benutzen. Die richtig notorischen C programmierer schreiben eine Schleife ohne for zu verwenden, also z.B.
1 | |
2 | |
Takao K. schrieb: > Die richtig notorischen C programmierer Real programmers can write FORTRAN programs in any language …
Gast
#3603753
Jörg Wunsch schrieb: > Dann nenne es „lokal zur Übersetzungseinheit“, wenn dir das Wort besser > als „Modul“ gefällt. Ach Jörg, laß dich nicht foppen. Es gibt halt mittlerweile zu wenige Leute, die des Pascales noch mächtig sind. Dort braucht man keine Headerdateien, dort kann man dediziert in der Quelle festlegen, welche Dinge des Moduls (oder nennen wir es einfach wieder "UNIT" - dieses Wort gefällt mir sowieso besser) von außen sichtbar sein sollen und welche nicht. Obendrein kann man dort Variablen mit feststehender Adresse ('absolute') vereinbaren. Das wäre wesentlich schicker und lesbarer als das Geprassel, was man sich bei µC in C antun muß, um eines der Hardware-Register zu beschreiben. Man hätte C schon längst reformieren können, anstatt immer noch eine Version draufzusetzen. Aber seit dem Übergang von K&R nach ANSI ist den Gremien wohl die Puste ausgegangen. Tja, mal wieder das alte Thema.. W.S.
W.S. schrieb: > welche Dinge des Moduls Das mit den Modulen war Modula. ;-)
W.S. schrieb: > Jörg Wunsch schrieb: >> Dann nenne es „lokal zur Übersetzungseinheit“, wenn dir das Wort besser >> als „Modul“ gefällt. > > Ach Jörg, laß dich nicht foppen. > Es gibt halt mittlerweile zu wenige Leute, die des Pascales noch mächtig > sind. Dort braucht man keine Headerdateien, dort kann man dediziert in > der Quelle festlegen, welche Dinge des Moduls (oder nennen wir es > einfach wieder "UNIT" - dieses Wort gefällt mir sowieso besser) von > außen sichtbar sein sollen und welche nicht. Obendrein kann man dort > Variablen mit feststehender Adresse ('absolute') vereinbaren. Das wäre > wesentlich schicker und lesbarer als das Geprassel, was man sich bei µC > in C antun muß, um eines der Hardware-Register zu beschreiben. > > Man hätte C schon längst reformieren können, anstatt immer noch eine > Version draufzusetzen. Aber seit dem Übergang von K&R nach ANSI ist den > Gremien wohl die Puste ausgegangen. > > Tja, mal wieder das alte Thema.. > > > W.S. Also ich finde C gut. mach doch mal einen Typ Cast in Pascal- es geht zwar, allerdings toll ist es nicht gerade. Ich finde C gut da ich es fast genauso wie Assembler verwenden kann. Es gibt unions und es gibt Funktionszeiger. Deklariere doch mal in Pascal ein Array mit funktionszeigern... Und ja, es gibt Anwendungen dafuer.
Gast
#3603829
Takao K. schrieb: > Es gibt unions und es gibt Funktionszeiger. Deklariere doch mal in > Pascal ein Array mit funktionszeigern... Hä? Wo lebst du? Also Erstens: Sowas wie unions gibt es auch in Pascal, nämlich records mit variablem Innenleben. Zweitens: Typecasts gibt es auch, wird aber wesentlich seltener benötigt als in C und ist einleichtender: typebezeichner(operand). function MyThreadProc(zahl:Pointer):longint; begin if (dword(zahl) and 16) <> 0 then blablabla.. Drittens:Funktionszeiger gibt es natürlich auch: type TWriter = procedure(S : String); TReader = function : char; var MyWriter : TWriter; MyReader : TReader; Man kann dann, nachdem man den entsprechenden Funktionspointer in MyReader und MyWriter eingetragen hat, MyReader und MyWriter wie normale Prozeduren bzw. Funktionen aufrufen. begin MyReader:= @UART_In; MyWriter:= @Drucker_Output; c:= MyReader; MyWriter('Hallo'); Also, wo ist dein Problem? Offenbar nur dieses, daß du Pascal nicht so recht kennst. W.S.
W.S. schrieb: > Sowas wie unions gibt es auch in Pascal, nämlich records mit variablem > Innenleben. Mit dem Unterschied, dass man den Varianten-Selektor dort zwangsweise als Bestandteil des Varianten-Records mit angeben muss, zumindest in Standard-Pascal. Pascal ist halt als Lehrsprache entwickelt worden und von da dann aufgebohrt, wobei die einzelnen Hersteller nicht alle den gleichen Bohrer benutzt haben. ;-) Herr Wirth wollte das dann mit Modula wieder ausgleichen, was aber bei weitem nicht die Verbreitung gefunden hat, die er sich gewünscht haben mag.
Jörg Wunsch schrieb: > W.S. schrieb: >> Sowas wie unions gibt es auch in Pascal, nämlich records mit variablem >> Innenleben. > > Mit dem Unterschied, dass man den Varianten-Selektor dort zwangsweise > als Bestandteil des Varianten-Records mit angeben muss, zumindest in > Standard-Pascal. > > Pascal ist halt als Lehrsprache entwickelt worden und von da dann > aufgebohrt, wobei die einzelnen Hersteller nicht alle den gleichen > Bohrer benutzt haben. ;-) Herr Wirth wollte das dann mit Modula > wieder ausgleichen, was aber bei weitem nicht die Verbreitung > gefunden hat, die er sich gewünscht haben mag. PASCAL ist keine wirklich neue Sprache, hat der Herr Wirth von PL/1 abgekupfert. habe mich jahrelang damit abgegeben und oft hatte ich halt Ideen, wurde aber von der Syntax eingeschraenkt. Und es hat halt den ruf einer Hobby und Bastelsprache. richtig eklig wird es wenn in Pascal pointer zusammengebaut werden sollten. In C ist es schon schlimm genug.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
Takao K. schrieb: > PASCAL ist keine wirklich neue Sprache, hat der Herr Wirth von PL/1 > abgekupfert. Ich hätte jetzt eher auf Algol (60/68) getippt. > Und es hat halt den ruf einer Hobby und Bastelsprache. Naja, sowas ist nicht unumstößlich. Ich habe zu CP/M-Zeiten gern in Turbo-Pascal programmiert, denn die Programmierumgebung war angenehm zu bedienen und recht flott (anders als die meisten C-Compiler und auch alternative Pascal-Implementierungen damals), und man hatte gegenüber Assembler den Vorteil einer deutlich effektiveren (bezüglich des zu spendierenden Zeitaufwands) Programmierung. Als der EPROMmer dann erstmal grundsätzlich lief, habe ich die innere Schleife in Inline-assembler nachgeschrieben. Danach war es sowohl schnell als auch gut bedienbar.
Jörg Wunsch schrieb: > Takao K. schrieb: > >> PASCAL ist keine wirklich neue Sprache, hat der Herr Wirth von PL/1 >> abgekupfert. > > Ich hätte jetzt eher auf Algol (60/68) getippt. > >> Und es hat halt den ruf einer Hobby und Bastelsprache. > > Naja, sowas ist nicht unumstößlich. Ich habe zu CP/M-Zeiten gern in > Turbo-Pascal programmiert, denn die Programmierumgebung war angenehm > zu bedienen und recht flott (anders als die meisten C-Compiler und > auch alternative Pascal-Implementierungen damals), und man hatte > gegenüber Assembler den Vorteil einer deutlich effektiveren (bezüglich > des zu spendierenden Zeitaufwands) Programmierung. Als der EPROMmer > dann erstmal grundsätzlich lief, habe ich die innere Schleife in > Inline-assembler nachgeschrieben. Danach war es sowohl schnell als > auch gut bedienbar. Zugegeben, als ich Schueler war in der Realschule, konnte ich mit C nicht viel anfangen. Das war installiert auf den Rechnern, aber zum Kompilieren mussten halt bestimmte Einstellungen gemacht werden. Internet oder Handbuecher gabs damals nicht. Bei Turbo Pascal war ja eine Hilfefunktion dabei. Habe ich dann z.B. verkettete Liste programmiert, und auch OOP ausprobiert. Dann Mitte der 1990er bin ich auf Assembler umgestiegen- da war halt das Schnuerkorsett weg. Wenn ich mir Pascal Programme heute mal anschaue, moechte ich das garnicht mehr machen. Heutzutage gibts ja internet, es ist viel einfacher eine Antwort auf ein bestimmtes Verstaendnissproblem zu erhalten. Wenn C erst einmal richtig verstanden wird, ist es sehr leistungsfaehig und die Art und Weise von Deklarierungen, Addressierung usw. ist sehr praktisch. z.B. mit MPLABX, gibt es Autocomplete fuer Strukturen, und Variablen einfach im Debugger anzeigen (auch fuer Array/Strukture). Das gabs 1990 nicht. So kann C dann auch recht schnell erlernt werden.
Gast
#3604152
Lothar Miller schrieb:
Auch wenn es schlimmeres gibt, macht es das Krücken C nicht besser.
Gast
#3604155
Peter Dannegger schrieb: > Es gibt schlimmere Doppelbelegungen. > > Z.B. wenn man eine Schleife verlassen will, geht das mit Break. > Hat man mehrere Abbruchbedingungen, würde sich ein Switch geradezu > anbieten und wäre auch am besten lesbar. > Dummm nur, daß dann das Break nicht die Schleife verläßt. > Hier kann man nur ein Goto zum Verlassen benutzen. Break und goto arbeiten unterschiedlich. Das ist dir schon bekannt, oder? Wer goto braucht, kann nicht programmieren. :-P
anti c schrieb: > Wer goto braucht, kann nicht programmieren. Ist auch mit Smiley eine unsinnige Aussage. Kennst du Donald Knuth? Er hat mal einen Aufsatz geschrieben "Structured Programming with Go To". Das war sein Protest gegen Dijkstras dogmatisch gepredigten Verzicht auf goto.
Jörg Wunsch schrieb: > anti c schrieb: >> Wer goto braucht, kann nicht programmieren. > > Ist auch mit Smiley eine unsinnige Aussage. > > Kennst du Donald Knuth? Er hat mal einen Aufsatz geschrieben > "Structured Programming with Go To". Das war sein Protest gegen > Dijkstras dogmatisch gepredigten Verzicht auf goto. Also ich will es garnicht mutmassen was Herr D. so privat macht wass Ihn in die Lage versetzt solch ein Pamphlet anzufertigen. Koennte ein Fall sein von "Ich will es garnicht wissen mir reicht schon was ich sehe". Und 20 Jahre spaeter dann so ein Krampf ein jeder plappert es nach, ja nicht auch nur ein GOT0 verwenden oder Bestien aus dem Hades werden sich manifestieren. Es ist total egal- im Endeffekt gibt es einen Assembler mit Switch Opcodes nicht. Nach einem Vergleich wird ja ohnehin ein GOTO verwendet wie sollte es anders gehen? Es wird halt nur nicht ausgeschrieben. Aus so einem Grund ist dieses Pamphlet halt ein Krampf.
Gast
#3604180
Von mir aus kann auch Donald Duck was dazu schreiben. Das goto zerstört den Programmfluss und macht die Software unübersichtlich. Im Profibereich also ein no go.
anti c schrieb: > Peter Dannegger schrieb: >> Es gibt schlimmere Doppelbelegungen. >> >> Z.B. wenn man eine Schleife verlassen will, geht das mit Break. >> Hat man mehrere Abbruchbedingungen, würde sich ein Switch geradezu >> anbieten und wäre auch am besten lesbar. >> Dummm nur, daß dann das Break nicht die Schleife verläßt. >> Hier kann man nur ein Goto zum Verlassen benutzen. > > Break und goto arbeiten unterschiedlich. Das ist dir schon bekannt, > oder? > > Wer goto braucht, kann nicht programmieren. :-P Was mir selbst zu eigen ist unterstelle ich halt anderen, um davon abzulenken. Da wird aus dem Rowdy in der Schule der dich schikaniert halt ein "Beschuetzer", er will dich ja nur abhaerten und er tut es nur damit es andere nicht tun. Alles Mueller oder was.
anti c schrieb: > Von mir aus kann auch Donald Duck was dazu schreiben. Das goto zerstört > den Programmfluss und macht die Software unübersichtlich. Im > Profibereich also ein no go. Kannste darueber lachen wenn du dir die Disassemblierung anschaust. Es zerstoert den Programfluss. Also wo denn, im Geiste? Wenn du verschachtelte switch statements hast, und dann break verwendest, musst du es halt schoen abarbeiten und viel Spass dabei. SWITCH erst garnicht verwenden. Wenn es nur bis zu 5 Vergeleiche sind, einfach mit IF abfragen ansonsten einen Parser mit Tabelle verwenden.
Gast
#3604195
Keiner pflegt ein Programm mit dem Disasm. Es geht um den reinen C Code. Foto ist böse, Foto ist sch.......leicht.
anti c schrieb: > Von mir aus kann auch Donald Duck was dazu schreiben. Nun, mit derart Überheblichkeit wirst du nicht weit kommen. Du verspottest etwas, ohne es dir überhaupt angesehen zu haben. > Das goto zerstört > den Programmfluss und macht die Software unübersichtlich. Im > Profibereich also ein no go. Beides Unsinn. Lassen wir das. Wir werden uns nicht einigen: ich kenne Knuths Gründe (und nicht mehr alle davon stimmen heutzutage), und ich weiß, wann ich selbst auch mal ein goto benutzen würde und wann lieber nicht. Übrigens: wenn du kein goto benutzen willst, dann musst du auch unter allen Umständen und komplett dogmatisch auf ein explizites "return" aus einer Funktion verzichten (ausgenommen ganz am Ende). Das ist nämlich auch nur ein verkapptes "goto". (Pascal hat sowas schließlich auch nicht. ;-)
Gast
#3604318
Jörg Wunsch (dl8dtl) (Moderator) schrieb: anti c schrieb: >> Von mir aus kann auch Donald Duck was dazu schreiben. > Nun, mit derart Überheblichkeit wirst du nicht weit kommen. Du > verspottest etwas, ohne es dir überhaupt angesehen zu haben. Wahrscheinlich ist "anti c" nur ein verkanntes, unbekanntes Genie und kann einiges mehr vorweisen, als "die paar Werke", die der "nur" Stanford Prof. Donald E. Knuth, Autor des Standardwerks "The Art of Computer Programming" sowie Urvater des Textsatzsystems TeX beigesteuert hat, siehe http://de.wikipedia.org/wiki/Donald_E._Knuth Und als "anti c" wird er mit Freude und Wonne den Pascal Code im angesprochenen Machwert über das "Pöse goto" förmlich in sich aufsaugen http://cs.sjsu.edu/~mak/CS185C/KnuthStructuredProgrammingGoTo.pdf und seine Bildungslücken damit eventuell ein wenig aufpolieren. Achja, ich hab das goto Paper übrigens auch nicht gelesen. Dafür aber u.A. das ein- oder andere TeX Buch mal von ihm gekauft und gelesen (laaange her).
Jörg Wunsch schrieb: > Real programmers can write FORTRAN programs in any language … To compile DO loops like god meant them to be.
Gast
#3604801
Jörg Wunsch schrieb: > Übrigens: wenn du kein goto benutzen willst, dann musst du auch unter > allen Umständen und komplett dogmatisch auf ein explizites "return" aus > einer Funktion verzichten (ausgenommen ganz am Ende). Das ist nämlich > auch nur ein verkapptes "goto". (Pascal hat sowas schließlich auch > nicht. ;-) Ob Fortran oder Pascal irgendetwas haben oder nicht, spielt doch keine Rolle. Ein goto ist in jeder Sprache Mist! Übrigens: gibt es einen großen Unterschied zwischen return und goto. Beim return weiss man genau wo es landet. In Unterprogrammen werden garantiert stack und Register nach return restauriert. Beim goto ist das Staunen des super spitzen Programmierers garantiert, wenn er damit wild durchs Programm springt. Ein guter Programmierer braucht kein goto! Es gibt keinen Fall, den man nicht genauso gut und viel besser nachvollziehbar hin bekommt. Nur weil es diesen Befehl gibt, muss er nicht sinnvoll sein und genutzt werden. :-P
anti c schrieb: > Ob Fortran oder Pascal irgendetwas haben oder nicht, spielt doch keine > Rolle. Ein goto ist in jeder Sprache Mist! Hast du das in der Schule / auf der Uni gelernt, oder sprichst du aus Erfahrung? Jeder gute, weise und erfahrene Programmierer wird dir sagen, dass deine Pauschalaussage falsch ist. Es gibt Fälle, wo ein goto sehr sinnvoll ist, den Programmfluss und die Intention des Programmierers viel klarer hervortreten lässt, und nebenbei noch viel ressourcenschonender ist. Aber dazu gehört eben Erfahrung, viel (extrem viel) Code lesen und verstehen. Aber natürlich ist es viel einfacher, "goto ist böse" nachzuplappern...
Michael Reinelt schrieb: > Jeder gute, weise und erfahrene Programmierer wird dir sagen, dass deine > Pauschalaussage falsch ist. Schon deshalb, weil man in FORTRAN (zumindest bis F77) praktisch nicht ohne GOTO auskam. ;-) anti c schrieb: > Nur weil es diesen Befehl gibt, muss er nicht sinnvoll sein und genutzt > werden. :-P Nur, weil du mal gehört hast, dass er böse wäre, heißt das noch lange nicht, dass es keine sinnvollen Einsatzfälle dafür gäbe.
Jörg Wunsch schrieb: > Schon deshalb, weil man in FORTRAN (zumindest bis F77) praktisch nicht > ohne GOTO auskam. ;-) Und, stell dir vor, ich hab mein ganzes Leben lang (leider) nie FORTRAN programmiert, und trotzdem verteidige ich das GOTO :-)
Gast
#3604925
Ich spreche aus Erfahrung. Und wie schon geschrieben: Es gibt keinen Fall, der nicht ohne goto für die Nachwelt besser verständlich und nachvollziehbar ist. Natürlich kann man mit einem goto aus einer for Schleife springen. Das ist einfach und überschaubar. Aber das geht mit einem break genauso gut. Goto ist mächtig und erlaubt Sprünge quer durchs Programm. Das ist gefährlich und bei einer vernünftigen Programmstruktur völlig unnötig. Ich bleigbe dabei: goto ist gefährlich und überflüssig!
anti c schrieb: > Ich spreche aus Erfahrung. Ah! Dann solltest dir vielleicht einen seriöseren Nick zulegen? Deiner klingt jetzt nicht grad nach 15 Jahren Programmiererfahrung und >1Mio LOC
Michael Reinelt schrieb: > Und, stell dir vor, ich hab mein ganzes Leben lang (leider) nie FORTRAN > programmiert Hast du nichts verpasst. :-) anti c schrieb: > Und wie schon geschrieben: Es gibt keinen Fall, der nicht ohne goto für > die Nachwelt besser verständlich und nachvollziehbar ist. Doch, gibt es. Aber die willst du ja gar nicht wissen.
Am besten auf Goto, Return verzichten und dafür Longjmp benutzen. Dann kann man sogar zwischen Interrupts und Funktionen hin und her springen.
Gast
#3604939
Jörg Wunsch schrieb: > anti c schrieb: > Und wie schon geschrieben: Es gibt keinen Fall, der nicht ohne goto für > die Nachwelt besser verständlich und nachvollziehbar ist. > > Doch, gibt es. Aber die willst du ja gar nicht wissen. Bla blab bla, wo ist den der Stein der Weisen?
anti c schrieb: > Ich spreche aus Erfahrung. > > Und wie schon geschrieben: Es gibt keinen Fall, der nicht ohne goto für > die Nachwelt besser verständlich und nachvollziehbar ist. > > Natürlich kann man mit einem goto aus einer for Schleife springen. Das > ist einfach und überschaubar. Aber das geht mit einem break genauso gut. > Goto ist mächtig und erlaubt Sprünge quer durchs Programm. Das ist > gefährlich und bei einer vernünftigen Programmstruktur völlig unnötig. > > Ich bleigbe dabei: goto ist gefährlich und überflüssig! also mit deinem Sprachgebrauch hast du wohl mal ein Beratungsgespraech noetig. Goto ist mächtig Nee ist es nicht. und erlaubt Sprünge quer durchs Programm Ja klar aber wer will das wirklich? Vielleicht siehst du es ein dass der Compiler aus dem C Source ein Assembler programm erzeugt, und dass ist voll mit GOTOs. Wie sollte denn ein IF funtionieren wenn nicht mit GOTO? Es ist nur eine andere Schreibweise. CMP Register, Value JNE Do_Something1 // Do_Something2 JMP Ready Do_Something1: // something Ready: Oder willst du est abstreiten dass die CPU genau dass macht? if (var=value) { do_something(); } else { do_something2(); } ein Lastwagen mit 80 KMH auf der Autobahn ist auch gefaehrlich.
Gast
#3604972
anti c (Gast) schrieb: Jörg Wunsch schrieb: >> anti c schrieb: >> Und wie schon geschrieben: Es gibt keinen Fall, der nicht ohne goto für >> die Nachwelt besser verständlich und nachvollziehbar ist. >> >> Doch, gibt es. Aber die willst du ja gar nicht wissen. > Bla blab bla, wo ist den der Stein der Weisen? Lies beispielsweise "Programmieren in C", Kernighan/Ritchie, 2. Ausgabe, Kapitel 3.8 goto und Marken Dort findet sich ein Beispiel was auch hier illustriert ist http://openbook.galileocomputing.de/c_von_a_bis_z/008_c_kontrollstrukturen_012.htm#mj42701038b17e1c01b0daef016a195d43 Deine Argumentationslinie ist, du versuchst ein Dogma aufzustellen (niemals, nicht goto !!), während andere im Regelfall goto für abwegig erklären, weil mans nicht braucht, aber dennoch die Ausnahme zulassen bzw. anerkennen.
Gast
#3604987
Takao K. (takao_k) schrieb: > Vielleicht siehst du es ein dass der Compiler aus dem C Source ein > Assembler programm erzeugt, und dass ist voll mit GOTOs. Diese Argumentation ist natürlich auch etwas fragwürdig, weil du damit gewissermaßen das Compilat dem Quellcode gleichstellst, nach dem Motto, im Endeffekt ist alles Assemblercode (oder Maschinencode). Das hieße dann aber auch, man könnte sich die ganze OOP mit dem ganzen "Klassengedöns" schenken, weil am Ende wird eh alles in einfachste Assembleranweisungen aufgelöst und von den Klassen bleibt nichts übrig. ;-)
Visualdingens schrieb: > Takao K. (takao_k) schrieb: > >> Vielleicht siehst du es ein dass der Compiler aus dem C Source ein >> Assembler programm erzeugt, und dass ist voll mit GOTOs. > > Diese Argumentation ist natürlich auch etwas fragwürdig, weil du damit > gewissermaßen das Compilat dem Quellcode gleichstellst, nach dem Motto, > im Endeffekt ist alles Assemblercode (oder Maschinencode). Das hieße > dann aber auch, man könnte sich die ganze OOP mit dem ganzen > "Klassengedöns" schenken, weil am Ende wird eh alles in einfachste > Assembleranweisungen aufgelöst und von den Klassen bleibt nichts übrig. > > ;-) Wieso denn? Es ist auch in Assembler moeglich, OOP zu verwenden, wurde sogar mal gemacht. C ist schon mit Assembler zu vergleichen, der Vorteil ist halt weniger Schreibarbeit, und es ist nicht von Befehlssatz abhaengig. Wenn ich einen Pointer dereferenziere, und einen Index hinzufuege, und dann noch inkrementiere, errinert dies schon sehr an bestimmte Assembler Addressierungsarten. In BASIC gehts dies nicht ausser man arbeitet mit einem Array und es ist dann sehr umstaendlich. In PASCAL geht es irgenwie so ein bisschen aber es ist ein Krampf (typ cast nach Integer, inkrementieren, typ cast nach pointer). In C wird Pointer Arithmetik halt direkt unterstuetzt, es ist ein Merkmal dieser Sprache. Modernes C++ arbeitet nicht mehr soviel mit Pointer Arithmetik. Hier werden (z.B. unter Windows) oft spezielle Spracherweiterungen verwendet (z.B. gibt es Array Lists, und den new operator). Da Windows aber so stark verbreitet ist, quasi ist es ein Standard. Ein modernes Windows programm laesst sich nict mehr gut mit Assembler vergleichen- teilweise wird es sogar zuerst in MSIL uebersetzt. Also nicht mehr vom Befehlssatz abhaengig. GOTO- Ich wuerde sagen +- 50 Zeilen ist in Ordnung. Viel laenger als einige Seiten sollte eine Funktion ohnehin nicht sein. Aus einer Funktion herausspringen ist nicht so gut, wegen des Stacks, wenn es ueberhaupt geht. In 95% aller Faelle wenn GOTO verwendet wird sind es vielleicht 10 Zeilen, und es kann die Lesbarkeit in bestimmten Faellen erhoehen. Insbesondere fuer Fehlerabfrage ist es einfach praktisch, nicht break zu verwenden, und dann eine Unmenge von Flags zu verwalten, sondern GOTO zu verwenden. In Windows C++ gibt es aber schon catch/try... Also wer ueber GOTO lamentiert dass es total schlimm ist es auch nur ein paar mal zu verwenden, dass ist halt kein richtiger Programmierer. Ich verwende GOTO so oft wie moeglich, immer dann wenn es Sinn macht, und gut oder "besser" aussieht. Warum denn eine Schleife verkrampfen, rueckwaerts laufen lassen und komplizierte tests einbauen, wenn es mit 2 GOTOs viel einfacher geht? z.B. denk mal ueber den Fall, wenn du Daten hast in einer Struktur, allerdings brauchen diese nicht alle 8 bits, also verwendest du im 1. Feld noch die 3 oberen bits fuer etwas anderes. Warum denn eine komplizierte Strukturdefinition, und umstaendliche Konstrukte? Der Sonderfall wird halt einfach einmal direkt abgefragt. OOP mag es hingegen nicht so sehr, weitgehend nur char* zu verwenden. Also auch wenn es eigentlich keine 8 bit chars sind, wird trotzdem ein char* pointer verwendet. Wozu dieser Datentyp Krampf wie in PASCAL, wenn es nicht wirklich zu irgendetwas nuetze ist, ausser um sicherzustellen, der Lehrer hat Recht, und der Student nicht. Warum also ist goto so verpönt? Aus Performance-Gründen! Durch goto wird der normale Ablauf des Programms einfach unterbrochen. http://openbook.galileocomputing.de/c_von_a_bis_z/008_c_kontrollstrukturen_012.htm Ist ja totaler Unsinn, das GOTO wird verwendet, weil der Progrmmablauf in einer bestimmten Art und Weise unterbrochen werden soll. Das ist einfach nur total falsch.
Jörg Wunsch schrieb: > Michael Reinelt schrieb: >> Und, stell dir vor, ich hab mein ganzes Leben lang (leider) nie FORTRAN >> programmiert > > Hast du nichts verpasst. :-) Doch - ich könnte in FORTRAN-Diskussionen besser mitreden ;-)
Gast
#3605176
Takao K. schrieb: > Hier > werden (z.B. unter Windows) oft spezielle Spracherweiterungen verwendet > (z.B. gibt es Array Lists, und den new operator). Da Windows aber so > stark verbreitet ist, quasi ist es ein Standard. Takao K. schrieb: > In Windows C++ gibt es aber schon catch/try... Wat? Alle diese Dinge sind im C++ Standard definiert und funktionierem damit in allen konformen Implementationen, wie zB GCC unter Linux - da ist überhaupt nix windows-spezifisch dran...
Dr. Sommer schrieb: > Takao K. schrieb: >> Hier >> werden (z.B. unter Windows) oft spezielle Spracherweiterungen verwendet >> (z.B. gibt es Array Lists, und den new operator). Da Windows aber so >> stark verbreitet ist, quasi ist es ein Standard. > > Takao K. schrieb: >> In Windows C++ gibt es aber schon catch/try... > Wat? Alle diese Dinge sind im C++ Standard definiert und funktionierem > damit in allen konformen Implementationen, wie zB GCC unter Linux - da > ist überhaupt nix windows-spezifisch dran... Gibts da auch schon Array Lists? Ich habe nicht behauptet das catch/try Windows spezifisch ist, eher so zu verstehen dass es catch/try in C nicht gibt.
Gast
#3605313
Takao K. schrieb: > also mit deinem Sprachgebrauch hast du wohl mal ein Beratungsgespraech > noetig. Wenn 's fachlich nicht reicht werden wir persönlich? Das kann ich auch: Was bist du überhaupt für ein hässlicher Kasper? Deine Beiträge in verschiedenen Threads deuten auf einen Azubi im ersten Jahr. Und dann hier so 'ne dicke Hose? Weiss noch nicht mal wie man 'nen PAL anpackt, aber hier rumunken! Das goto habe ich mit Basic unter CP/M abgelegt. Weil man es nicht braucht, weil es nur verwirrt. Und du Takao hast mit Sicherheit noch nie eine Prolemstellung gehabt, die ein goto erfodern könnte.
Gast
#3605373
Takao K. (takao_k) schrieb: > Warum also ist goto so verpönt? Aus Performance-Gründen! Durch goto wird > der normale Ablauf des Programms einfach unterbrochen. > http://openbook.galileocomputing.de/c_von_a_bis_z/... > Ist ja totaler Unsinn, das GOTO wird verwendet, weil der Progrmmablauf > in einer bestimmten Art und Weise unterbrochen werden soll. > Das ist einfach nur total falsch. Du hast dich hier auf einen Nebensatz des Autors eingschossen, den du im übrigen nicht mal als Zitat wiedergegeben hast. Die Schlussfolgerung des Autors finde ich auch missglückt und unzutreffend. Aber das Beispiel um das es ging ist genau das Beispiel aus dem Kernighan/Ritchie. Der Autor hat im übrigen klar herausgestellt, dass ein goto in C für ihn im Regelfall wohl keinen guten Programmierstil darstellt. Wenn du dem Autor Ungenauigkeit vorwirfst, nun die hast du auch. Dein Satz hier > Vielleicht siehst du es ein dass der Compiler aus dem C Source ein > Assembler programm erzeugt, und dass ist voll mit GOTOs. ist jedenfalls kein Argument für ein goto. Stell dir vor, du hast eine Programmiersprache in der es kein goto gibt. Dennoch wird das Compilat immer auch Sprungbefehle ("goto"'s) aufweisen. Ganz einfach, weil Prozessoren nun mal ohne Sprungbefehle nicht auskommen bzw. es im Regelfall keine Prozessoren ohne Sprungbefehle gibt. Oder stell dir vor, das goto wird in einer Neudefinition von C mal abgeschafft (nicht zu erwarten). Dann sticht dein Argument auch nicht mehr. Oder das Beispiel auf das dich Dr. Sommer (Gast) hingewiesen hat (catch/try). Auch da warst du reichlich ungenau. Aber es ist müßig sich am goto abzuarbeiten. Wer es nutzen möchte soll es tun und wer nicht, wird seine Gründe dafür haben.
Gast
#3605393
Takao K. schrieb: > Gibts da auch schon Array Lists? Kommt drauf an was du damit meinst. Array List ist irgendwie ein Widerspruch in sich - was denn jetzt, Array oder Liste? Es gibt std::vector - quasi ein intelligentes Array, std::list - eine doppelt verkettete Liste, std::deque - eine Doppel-Queue die als blockweise verkettete Liste implementiert werden kann. Und was heißt hier "schon", Windows/Microsoft ist jetzt nicht gerade ganz vorne bei der C++ Entwicklung. GCC und Clang sind da weiter...
Gast
#3605485
Takao K. schrieb: > Viel laenger als > einige Seiten sollte eine Funktion ohnehin nicht sein. Hier wird nicht über den 25 Zeilen Textmodus geschrieben. Takao K. schrieb: > Aus einer Funktion herausspringen ist nicht so gut, wegen des Stacks, > wenn es ueberhaupt geht. Er weiss, wie goto funktioniert??? Takao K. schrieb: > Ich verwende GOTO so oft wie moeglich, immer dann wenn es Sinn macht, > und gut oder "besser" aussieht. 1. Lehrjahr und nicht E-Technik, oder er nutzt ROM-Basic. ;-) Takao K. schrieb: > Warum denn eine Schleife verkrampfen, rueckwaerts laufen lassen Jetzt aber so richtig ... :-(((
Gast
#3606554
anti c schrieb: > Ich spreche aus Erfahrung. > > Und wie schon geschrieben: Es gibt keinen Fall, der nicht ohne goto für > die Nachwelt besser verständlich und nachvollziehbar ist. > > Natürlich kann man mit einem goto aus einer for Schleife springen. Das > ist einfach und überschaubar. Aber das geht mit einem break genauso gut. Es sei denn, es ist mehr als eine Schleifen-Ebene. Was sieht für dich eleganter aus?
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
oder
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
Ich finde das ohne diese umständliche Hilfsvariable besser lesbar. > Goto ist mächtig und erlaubt Sprünge quer durchs Programm. Das ist > gefährlich und bei einer vernünftigen Programmstruktur völlig unnötig. Ein Messer erlaubt es, Menschen zu erstechen. Das ist auch gefährlich. Dennoch sind Messer sehr nützlich, wenn man sie richtig verwendet. Nur weil man mit einem Sprachkonstrukt etwas schlechtes machen könnte, wird dieser dadurch nicht automatisch böse und muß zwingend vermieden werden.
Rolf Magnus schrieb: > Ich finde das ohne diese umständliche Hilfsvariable besser lesbar. Das sind auch ungefähr so die Sachen, die Knuth in seinem Aufsatz damals angebracht hat.
anti c schrieb: > Takao K. schrieb: >> Viel laenger als >> einige Seiten sollte eine Funktion ohnehin nicht sein. > Hier wird nicht über den 25 Zeilen Textmodus geschrieben. > Sondern 26 Zeilen. > Takao K. schrieb: >> Aus einer Funktion herausspringen ist nicht so gut, wegen des Stacks, >> wenn es ueberhaupt geht. > Er weiss, wie goto funktioniert??? > Nicht so richtig aber es wird immer besser. > Takao K. schrieb: >> Ich verwende GOTO so oft wie moeglich, immer dann wenn es Sinn macht, >> und gut oder "besser" aussieht. > 1. Lehrjahr und nicht E-Technik, oder er nutzt ROM-Basic. ;-) > Klempnerlehre geschmissen. > Takao K. schrieb: >> Warum denn eine Schleife verkrampfen, rueckwaerts laufen lassen > Jetzt aber so richtig ... :-((( Warum eigentlich Schleife? Das sollte GOTO Konstrukt heissen.
> Ein Messer erlaubt es, Menschen zu erstechen. Das ist auch gefährlich. > Dennoch sind Messer sehr nützlich, wenn man sie richtig verwendet. > Nur weil man mit einem Sprachkonstrukt etwas schlechtes machen könnte, > wird dieser dadurch nicht automatisch böse und muß zwingend vermieden > werden. Als Assemblerprogrammier weisst Du dass es verschachtelte Index garnicht wirklich gibt: i=0; rl:;if(data[i++]!=value)if(i<[xs*ys])goto rl; Behaupte ich nicht dass es guter Programmierstil ist aber aus FOR wird am Ende halt immer GOTO. Halt am Ende noch ein Dummy Element einbauen oder es muss nochmal getestet werden.
Rolf Magnus schrieb: > Was sieht für dich eleganter aus?
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
Oliver
Oliver S. schrieb: > Rolf Magnus schrieb: >> Was sieht für dich eleganter aus? > >
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
> > Oliver Für mich sieht es falsch aus :-) (increment in der while-Bedingung wird zu früh ausgeführt, du kommst nie mit x=0 oder y=0 in die Schleife)
Ich hätte aber auch noch Anwendungen, die von GOTO profitieren: Du hast in einer Funktion viele Prüfungen und Rücksprungpunkte. So in der Art:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
Das ist die klassische Variante eines "getarnten goto" Problem: wenn a,b,c allokierte Ressourcen sind, muss man die wieder freigeben. Damit fällt das "einfache" return schon mal aus. Man kann jetzt natürlich vor jedem return die bisher allokierten Ressourcen freigeben. Unschön, weil ich das mehrmals machen muss. natürlich kann man jetzt beliebig tiefe if's verschachteln:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
Das wird aber schnell extrem unübersichtlich. ich bevorzuge hier durchaus die goto-Variante:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
(nicht ganz korrekt, soll aber nur das Prinzip andeuten)
Gast
#3606949
Michael Reinelt schrieb: > Das wird aber schnell extrem unübersichtlich Daher wurde C++ erfunden, und eines seiner wichtigstes Features: Destruktoren.
1 | |
2 | |
3 | |
4 | |
Kurz, elegant, effizient und goto-frei... Wenn man dann noch exceptions verwendet, kann man sich die 3 if's sparen.
Dr. Sommer schrieb: > Daher wurde C++ erfunden, und eines seiner wichtigstes Features: > Destruktoren. Korrekt. Aber gehen wir mal davon aus dass wir entweder keine Destruktoren haben (C ohne ++) oder der Job nach dem "Out:" sich nciht über Destruktoren abwickeln lässt... > Wenn man dann noch exceptions verwendet, kann man sich die 3 if's sparen. Wobei eine Exception auch nur wieder ein getarntes goto ist ;-) Nebenbei: Exceptions werden meiner meinung nach auch viel zu inflationär verwendet. ich habe zu viel Code gesehen, wo man vor lauter try/catch dem code nicht mehr folgen kann...
Michael Reinelt schrieb: > Für mich sieht es falsch aus :-) Das kann durchaus sein, das war nur so "dahingerotzt"... > (increment in der while-Bedingung wird zu früh ausgeführt, du kommst nie > mit x=0 oder y=0 in die Schleife) Das allerdings kann nicht sein... Oliver
Gast
#3606970
Michael Reinelt schrieb: > Dr. Sommer schrieb: >> Daher wurde C++ erfunden, und eines seiner wichtigstes Features: >> Destruktoren. > > Korrekt. Aber gehen wir mal davon aus dass wir entweder keine > Destruktoren haben (C ohne ++) Einfach mit "g++" statt "gcc" kompilieren, dann hat man sie ;-) > oder der Job nach dem "Out:" sich nciht > über Destruktoren abwickeln lässt... Wie kann das denn? Destruktoren können beliebigen Code enthalten. >> Wenn man dann noch exceptions verwendet, kann man sich die 3 if's sparen. > Wobei eine Exception auch nur wieder ein getarntes goto ist ;-) So wie if, while, for, Funktionsaufrufe... > Nebenbei: Exceptions werden meiner meinung nach auch viel zu inflationär > verwendet. ich habe zu viel Code gesehen, wo man vor lauter try/catch > dem code nicht mehr folgen kann... Dann hat der Autor dieses Codes Exceptions nicht verstanden. Guter Exception-sicherer Code enthält nur sehr wenige try/catch-Blöcke und regelt das Aufräumen jeweils über... Destruktoren. In Java z.B. geht das natürlich nicht weswegen man sich dort mit try/catch behfelfen muss - einer der Gründe, warum C++ besser als Java ist.
Dr. Sommer schrieb: > Kurz, elegant, effizient und goto-frei... Premature return ist doch nur ein verkapptes GOTO, und nach der „reinen Lehre“ ebenfalls nicht zulässig. ;-)
Gast
#3606979
Jörg Wunsch schrieb: > Premature return ist doch nur ein verkapptes GOTO, und nach der > „reinen Lehre“ ebenfalls nicht zulässig. ;-) Deswegen ja Exceptions :-P Die hab ich im Original-Code zwecks Verständlichkeit zunächst ausgeblendet...
Dr. Sommer schrieb: > Deswegen ja Exceptions :-P Na ja, für sowas hier:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
muß man jetzt keine Exception auspacken, wenn NULL dort kein fehlerhafter Wert des pointer ist, und es auch nichts per Destruktor aufzuräumen gibt. Oliver
Oliver S. schrieb: >> (increment in der while-Bedingung wird zu früh ausgeführt, du kommst nie >> mit x=0 oder y=0 in die Schleife) > > Das allerdings kann nicht sein... Denke ich schon:
1 | |
2 | |
3 | |
4 | |
zählt von 1 bis 10 (und nicht von 0 bis 9)
Gast
#3607010
Oliver S. schrieb: > muß man jetzt keine Exception auspacken, wenn NULL dort kein > fehlerhafter Wert des pointer ist, und es auch nichts per Destruktor > aufzuräumen gibt. ICH habe ja nichts gegen ein einfaches return gesagt ;-)
Michael Reinelt schrieb: > Oliver S. schrieb: >>> (increment in der while-Bedingung wird zu früh ausgeführt, du kommst nie >>> mit x=0 oder y=0 in die Schleife) >> >> Das allerdings kann nicht sein... > > Denke ich schon: >
1 | |
2 | |
3 | |
4 | |
5 | |
> zählt von 1 bis 10 (und nicht von 0 bis 9)
1 | |
2 | |
sowas geht halt in BASIC oder PASCAL nicht. Am besten noch so ein paar x und i global bereithalten. Das sollte dann aber nur in kleineren Embedd C Programmen gemacht werden. Also nicht etwa dass ich es wirklich anrate. vielleicht gehts ja garnicht richtig, nicht ausgetestet...
Michael Reinelt schrieb: > Wobei eine Exception auch nur wieder ein getarntes goto ist ;-) Viel schlimmer noch: Das sind getarnte Longjumps. Und die sind an Bösartigkeit wohl kaum noch zu übertreffen. SCNR ;-)
Gast
#3607781
Dr. Sommer schrieb: > Jörg Wunsch schrieb: >> Premature return ist doch nur ein verkapptes GOTO, und nach der >> „reinen Lehre“ ebenfalls nicht zulässig. ;-) > Deswegen ja Exceptions :-P Das ist auch nur ein besser verstecktes "premature return". Die Idee dieser "Lehre" ist ja, nur genau einen einzigen Punkt zu haben, an dem die Funktion verlassen wird, nämlich am Ende. Das ist mit Exceptions auch nicht gegeben, es sei denn, ich fange in jeder Funktion alle Exceptions ab. Yalu X. schrieb: > Michael Reinelt schrieb: >> Wobei eine Exception auch nur wieder ein getarntes goto ist ;-) > > Viel schlimmer noch: Das sind getarnte Longjumps. Und die sind an > Bösartigkeit wohl kaum noch zu übertreffen. Früher waren beim GCC die Exceptions ja sogar über Longjump implementiert. Heute wird das aber meines Wissens anders gehandhabt.
Rolf Magnus schrieb: > Heute wird das aber meines Wissens anders gehandhabt. Die longjmp-Implementierung ist glaub' ich nach wie vor als Fallback möglich, falls eine bestimmte Architektur nichts besseres zu bieten hat. Die hat irgendwas mit "sjlj" im Namen, für "setjump/longjmp".
Gast
#3607869
Yalu X. schrieb: > Viel schlimmer noch: Das sind getarnte Longjumps. Und die sind an > Bösartigkeit wohl kaum noch zu übertreffen. Jo, aber Exceptions können nur aus Funktionen *raus*springen - am Stack nach oben - und rufen auch "sauber" Destruktoren auf. Daher würde ich sie als weit weniger bösartig als longjmp sehen, und auch sauberer als manuelle (fehleranfällige) Fehlerbehandlung & Aufräumen. Wenn man partout nur einen Exit-Punkt in einer Funktion haben will wird man wohl zwangsläufig ziemlichen Spaghetticode (endlose if-else-Ketten) produzieren?!
Gast
#3608004
Dr. Sommer schrieb: > Wenn man partout nur einen Exit-Punkt in einer Funktion haben will wird > man wohl zwangsläufig ziemlichen Spaghetticode (endlose if-else-Ketten) > produzieren?! Es sei denn, man benutzt goto ;-)
Gast
#3608051
Rolf Magnus schrieb: > Es sei denn, man benutzt goto ;-) Mit goto aus Schleifen und if's rauszuspringen um dann einen einzigen Exit-Punkt in der Funktion zu haben ist irgendwie... inkonsequent? Widersinnig? Bescheuert? :-D
Rolf Magnus schrieb: > Dr. Sommer schrieb: >> Wenn man partout nur einen Exit-Punkt in einer Funktion haben will wird >> man wohl zwangsläufig ziemlichen Spaghetticode (endlose if-else-Ketten) >> produzieren?! > > Es sei denn, man benutzt goto ;-) Oder garkeine Fehlerbehandlung, muss halt der Reset Taster gedrueckt werden, oder das FAT FFS ist kaputt... Lesen geht ja noch, aber wenn Dateien geschrieben werden, sollte am besten die Versorgungsspannung ueberwacht werden, und alle Fehler genau ausgetestet werden. Muesste halt ganz konkret gegenueber gestellt werden wie es mit, und ohne GOTOs aussieht (Ich gehe jetzt mal von embedded C aus). Unter Windows kann man sich auch nicht total darauf verlassen dass eine Allokierung von irgenetwas auch geklappt hat, koennte ja sein, der Speicher ist knapp, oder ein Skrip laeuft gerade Irre. Genaugenommen muss es immer ausgetestet werden, und im Fehlerfall muss zu einem sinnvollen Punkt zurueckgefunden werden. Hier auch nie darauf verlassen das ein Requester ueberhaupt geoeffnet werden kann. Nach einigen Wochen ohne Reboot ist das System manchmal sosehr zerschossen, dass es nicht mehr ohne reboot geht. GOTO oder nicht ist da eher noch eine Nebensache, mal davon abgesehen ob eine Fehlerbehandlung ueberhaupt durchgehend eingebaut wird, oder es halt bestenfalls einen Requester mit einer krausen Message gibt, und RETRY CANCEL ABORT. Unter Windows sind Programme oft uebervorsichtig, es wird dann abgebrochen, unter LINUX gibts jede Menge Fehlermeldungen in der Konsole, macht aber nicht wirklich etwas, und dass Programm kann trotzdem noch weitgehend genutzt werden. Wenn es mehrere Threads gibt kann ohnehin nicht einfach so hin und hergesprungen werden. Solche Software wird dann oft garnicht mehr mit klassischen verschachtelten Schleifen, if und case Kontrukten aufgebaut, sondern diese ist dann weitgehend mit Skripts realisiert. Diese koennen an C angelehnt sein, es kann binaercode in Tabellen sein, oder eine spezialisierte Skriptsprache mit richtigem Parser. MPLABX verwendet z.B. nicht mehr soviel Windows, sondern Java, und vielzaehlige Module. Wenn z.B. der Debugger spinnt, geht die IDE trotzdem noch. Unbedingt mal "Writing Secure Software" von Microsoft lesen.
Dr. Sommer schrieb: > Rolf Magnus schrieb: >> Es sei denn, man benutzt goto ;-) > Mit goto aus Schleifen und if's rauszuspringen um dann einen einzigen > Exit-Punkt in der Funktion zu haben ist irgendwie... inkonsequent? > Widersinnig? Bescheuert? :-D Okay, noch ein Vorschlag:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
Wie geht das sch"oner mit Exceptions / Destruktoren?? Ich hab sowas in
einem realen Programm drin ('mxli'), es geht hier nicht um graue
Theorie, sondern um stufenweise Initialisierung und eben auch passende
Aufraeumarbeiten im Fehlerfall.
Gast
#3608215
Takao K. schrieb: DAS ist halt der Vorteil von Exceptions - man kann seinen Code einfach so schreiben als träten nie Fehler auf, und wenn doch stürzt das Programm wenigstens "sauber" ab anstelle von irgendeinen potentiell gefährlichen Unsinn zu machen... Marc P. schrieb: > Wie geht das sch"oner mit Exceptions / Destruktoren? So: http://ideone.com/3lNflM Man programmiert sich EIN mal eine Klasse pro Resourcen-Typ inklusive Destruktor zum Aufräumen, initialisiert im Konstruktor und wirft evtl. eine Exception, und muss dann wie in tuwas() gezeigt einfach nur noch Instanzen davon anlegen. Dort braucht man dann überhaupt keine explizite Fehlerbehandlung mehr (kein goto, kein if) und kann so programmieren als könnte nichts schief gehen. Sowohl Im Fehler (Exception) -Fall als auch im Erfolgs-Fall wird dann ordentlich genau das aufgeräumt was aufgeräumt werden muss. Hier haben wir natürlich ein gewisses Missverhältnis zwischen "Hilfs-Code" (die Klassen) und dem eigentlichen Algorithmus ("tuwas"), aber typischerweise implementiert man sich einmal so eine Klasse (wie zB std::ifstream für eine Datei) und verwendet sie dann in vielen großen Algorithmen, die dadurch viel kürzer und einfacher werden.
Gast
#3608233
PS.: Und mit den so definierten Klassen kann man dann viele Funktionen im "tuwas"-Stil schreiben und erhält saubere Fehlerbehandlung mit nur einem einzigen try-catch-Block im Programm - dank Destruktoren.
Gast
#3608235
Dr. Sommer schrieb: > DAS ist halt der Vorteil von Exceptions Nicht von Exceptions, sondern von RAII. Wenn ich zwischendrin ein return machen würde (oder ein goto) statt eine Exception zu werfen, würde das genauso funktionierten. Auf der anderen Seite funktiniert es aber nicht in Sprachen, die zwar Exceptions, aber keine vernünftigen Destruktoren haben, da im Exception-Fall die Ressourcen eben nicht unbedingt automatisch aufgeräumt werden. Lustigerweise fehlen (deterministische) Destruktoren in einigen Sprachen gerade deshalb, weil sie einen Garbage Collector haben, der ja eigentlich für das automatische Aufräumen da ist. Dies ist aber leider inkonsequent umgesetzt, da ausschließlich Speicher und keine anderen Ressourcen behandelt werden. Um die muß man sich dann wieder von Hand kümmern.
Gast
#3608239
Rolf Magnus schrieb: > Nicht von Exceptions, sondern von RAII. Ohne Exceptions hätte man aber im o.g. Fall (= wenn man Fehler nicht explizit behandelt) ein Problem. Also wenn schon dank RAII+Exceptions.
Gast
#3608254
Michael Reinelt schrieb: > Denke ich schon: > int x; > while (x++ < 10) { > printf ("x=%d\n", x); > } > zählt von 1 bis 10 (und nicht von 0 bis 9) Noe. x hat irgendeinen Wert, da x nicht initialisiert wurde. Damit laeuft die schleife im schlechtesten falle endlos, wenn x zu beginn der schleife >=10 (weil nicht initialisiert) ist und x nach dem overflow wieder einen Wert bekommt der >= 10 ist. Das koennte passieren, da das verhalten bei einem signed overflow ja nicht definiert ist. anti c schrieb: > Das goto zerstört > den Programmfluss und macht die Software unübersichtlich. Im > Profibereich also ein no go. Schon mal in einen Kernel(z.B. Linux) oder in Treiber geschaut? Oder ist Kernel-/Treiberprogrammierung kein Profibereich?
Dr. Sommer schrieb: > Sowohl Im Fehler (Exception) -Fall als auch > im Erfolgs-Fall wird dann ordentlich genau das aufgeräumt was aufgeräumt > werden muss. Verstanden. Interessant ist die Ausgabe (zuerst 'cleanup A' dann 'B failed') aber natuerlich logisch. > Hier haben wir natürlich ein gewisses Missverhältnis zwischen > "Hilfs-Code" (die Klassen) und dem eigentlichen Algorithmus ("tuwas"), Leider gibt es aber auch Faelle, bei denen man weiss, dass man die Klassen nicht wiederverwerten wird, weil das Problem zu speziell ist. Ich verstehe meine Wahl des goto mittlerweile so: aufgrund diverser Kompromisse die ich im Vorfeld einging (ich bin ein grosser Fan von Speicher auf dem Stack, nicht auf dem Heap anzulegen; meine Variablen sind immer so lokal wie moeglich und werden nicht dupliziert; die Funktion parst die Kommandozeile, was vieles in der Reihenfolge laufzeit-bestimmt macht; ...) war die Wahl des goto das geringere Uebel. Es ist nicht das Konstrukt goto das ich so mag, sondern der Kontext, der das goto als einzig einfachen = (kurzen) Ausweg uebrig liess. Der heftigste Kompromiss meines Programms ist wohl der: es ist ein C-Programm (ohne ++). Schade, dass ich nicht weiss, ob ich in einem C++-Programm ebenso gehandelt haette.
Gast
#3608535
Marc P. schrieb: > Verstanden. Interessant ist die Ausgabe (zuerst 'cleanup A' dann 'B > failed') aber natuerlich logisch. Ja das muss natürlich so. > >> Hier haben wir natürlich ein gewisses Missverhältnis zwischen >> "Hilfs-Code" (die Klassen) und dem eigentlichen Algorithmus ("tuwas"), > > Leider gibt es aber auch Faelle, bei denen man weiss, dass man die > Klassen nicht wiederverwerten wird, weil das Problem zu speziell ist. Dann kann man sich so behelfen: http://ideone.com/5qJKch Man schreibt pro durchzuführender Aufräum-Aktion ein
1 | |
Die wird dann garantiert immer durchgeführt, wenn die Funktion zurückkehrt - unabhängig ob per "return", Erreichen des "}", oder Exception - allerdings nur, wenn die Ausführung zuvor eben diese Zeile erreicht hat (wenn die Funktion zuvor zurückgekehrt ist, nicht). > Ich verstehe meine Wahl des goto mittlerweile so: aufgrund diverser > Kompromisse die ich im Vorfeld einging (ich bin ein grosser Fan von > Speicher auf dem Stack, nicht auf dem Heap anzulegen; Sollte man immer machen, da der Stack viel schneller ist... > meine Variablen > sind immer so lokal wie moeglich und werden nicht dupliziert; Auch sehr sinvoll, um klarzustellen was sie alles beeinflussen > Der heftigste Kompromiss meines Programms ist wohl der: es ist ein > C-Programm (ohne ++). Schade, dass ich nicht weiss, ob ich in einem > C++-Programm ebenso gehandelt haette. Du kannst ja wie gesagt einfach mit "g++" statt "gcc" kompilieren und schon hast du ein C++ Programm in dem du alle o.g. Nettigkeiten anwenden kannst.
Dr. Sommer schrieb: > auto irgendeinFreierBezeichner = cleanup ([&] () { /* hier aufräumaktion > */ }); Wow! Seit wann? 'Anonyme' Funktionen? Das werde ich sicher verwenden! Danke fuer den Tip!!
Gast
#3608640
Marc P. schrieb: > Wow! Seit wann? 'Anonyme' Funktionen? Das werde ich sicher verwenden! > Danke fuer den Tip!! Seit 2011 (C++11) - neben eine Menge anderer toller Features. Ist in der Tat äußerst praktisch ;-)
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.