Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
OpenglerF hat geschrieben:
typedef ist meiner Ansicht nach aber eben keine storage-class, sondern gibt eine Typdefintion an. Schließlich wird nichts im Programm gespeichert, sondern ein anderer Name für einen Typen festgelegt. Außer dass zufällig beide male ein bestehender Typname und ein neuer Identifier benötigt werden, hat das nix miteinander zu tun und es werden völlig unterschiedliche Dinge getan.
Laut Standard ist es aber syntaktisch eben doch ein "storage-class specifier". Das erklärt auch einiges der Weirdness von typedef.
OpenglerF hat geschrieben:
C++11 hat dafür ja auch eine andere, verständlichere und konsequentere Schreibeweise mit "using" eingeführt.
Ich finde die Schreibweise mit "using" auch deutlich besser, aber hier gehen die Meinungen, insbesondere beim Punkt der "Konsequenz", stark auseinander.
Denn yurnharla hat mit einem Recht: Die Syntax von C verwendet vieles wieder, wie man an obigem Beispiel sieht, und ist damit ziemlich Konsequent. Das hat den Vorteil, dass man, wenn man ein Konstrukt an der einen Stelle verstanden hat, das Konstrukt auch an anderen Stellen versteht. Dass man dazu im Falle von typedef aber wissen muss, dass sich dieses syntaktisch wie ein storage-class specifier verhält (was mir auch neu war, und einiges erklärt), ist halt echt unschön; das ist definitiv nicht "Least Surprise", weil eben keine Storage Class festgelegt wird, sondern ein Typ definiert.
Wenn man C-kompatiblen Code schreiben will, muss man auf "using" leider sowieso verzichten.
viele Grüße, Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Joa, dass das deshalb so seltsam ist, war mir bislang auch nicht bewusst. Auch wenn es den Syntax erklärt, ergibt es trotzdem meiner Meinung nach keinen Sinn, wie du ja auch meintest. Also halte ich den Kritikpunkt aufrecht, denn konsequent ist meiner Meinung nach nur dann etwas, wenn mehrere gleiche Dinge dem gleichen Syntax folgen. Da es sich bei einer Typdefintion überhaupt nicht um das Gleiche wie bei einer Variablendefinition handelt, auch wenn wie erwähnt mehr oder weniger zufällig die gleichen Angaben notwendig sind, ist es meiner Ansicht nach alles andere als konsequent.
@mathias Also ich bin jetzt kein Pascal-Profi und kann es daher nicht mit Sicherheit sagen, allerdings scheint es mir, als ob Records wohl im Prinzip Strukturen sind. Mir geht es um folgende Austauschbarkeit: Kontrollstrukturen in C wie "while(...)" "if" oder "for" erwarten einen Befehl in C.
Code:
if(MyExpression)
DoSomething();
while(MyExpression)
DoSomething();
for(int i =0; i <256;++i)
DoSomething();
Und es gibt die {} um mehrere Statements zusammenzuschließen.
Code:
if (MyExpression)
{
DoSomething0();
DoSomething1();
}
while (MyExpression)
{
DoSomething0();
DoSomething1();
}
for(int i = 0; i < 256; ++i)
{
DoSomething0();
DoSomething1();
}
Das ist sehr konsequent und kompakt, wenn man, wie relativ häufig der Fall ist, nur ein Statement braucht. Aber die Konzepte sind unabhänig, man kann nämlich außerdem den Scope an anderen Stellen damit einschränken und somit zum Beispiel lokale Variablen in ihrem Bereich schützen.
Code:
{//Die Klammern beschränken den Scope von "Value". Das ist sehr nützlich mit RAII in C++,
//kann die Übersichtlichkeit erhöhen und verhindert den Missbrauch von "Value" außerhalb
Mir scheint, du hast immernoch nicht verstanden worauf ich hinaus will: Mir ist klar, dass es in Pascal Kontrollstrukturen gibt, allerdings gibt es weder a) Kontrollstrukturen ohne "end" noch b) Blöcke mit Scope. (den scheint es eh kaum zu geben, wegen funktionsglobaler Variablendefinition)
Registriert: Mo Nov 08, 2010 18:41 Beiträge: 769
Programmiersprache: Gestern
Lord Horazont hat geschrieben:
OpenglerF hat geschrieben:
typedef ist meiner Ansicht nach aber eben keine storage-class, sondern gibt eine Typdefintion an. Schließlich wird nichts im Programm gespeichert, sondern ein anderer Name für einen Typen festgelegt. Außer dass zufällig beide male ein bestehender Typname und ein neuer Identifier benötigt werden, hat das nix miteinander zu tun und es werden völlig unterschiedliche Dinge getan.
Laut Standard ist es aber syntaktisch eben doch ein "storage-class specifier". Das erklärt auch einiges der Weirdness von typedef.
OpenglerF hat geschrieben:
C++11 hat dafür ja auch eine andere, verständlichere und konsequentere Schreibeweise mit "using" eingeführt.
Ich finde die Schreibweise mit "using" auch deutlich besser, aber hier gehen die Meinungen, insbesondere beim Punkt der "Konsequenz", stark auseinander.
Denn yurnharla hat mit einem Recht: Die Syntax von C verwendet vieles wieder, wie man an obigem Beispiel sieht, und ist damit ziemlich Konsequent. Das hat den Vorteil, dass man, wenn man ein Konstrukt an der einen Stelle verstanden hat, das Konstrukt auch an anderen Stellen versteht. Dass man dazu im Falle von typedef aber wissen muss, dass sich dieses syntaktisch wie ein storage-class specifier verhält (was mir auch neu war, und einiges erklärt), ist halt echt unschön; das ist definitiv nicht "Least Surprise", weil eben keine Storage Class festgelegt wird, sondern ein Typ definiert.
Wenn man C-kompatiblen Code schreiben will, muss man auf "using" leider sowieso verzichten.
viele Grüße, Horazont
Nun ich denke es liegt einfach daran das Speicherklassen sehr nahe an das Verhalten rankommen. Sprich eine Storage-Class darf sich nicht innerhalb der Deklaration ändern, die Verwendbarkeit ändert sich (Stichwort register und Initialisierung), der ganze andere Kram wie const usw. wird benötigt und naja... die Bedeutung ändert sich halt sehr drastisch oder?
Das einzige was ich halt blöd finde ist das C hier keine Reihenfolge festlegt. Static usw. kann man ja auch hinter dem Typen stellen.... (dabei sterben übrigens kleine Kätzchen)
[edit]
Ich persönlich finde using übrigens albern an der Stelle weil C++ Namespaces ja wirklich etwas komplett anderes sind.... Hätte man sich eher für Module oder so aufsparen sollen. Aber naja static wird ja schließlich auch vergewaltigt ...
@OpenglerF
Naja Operator-Overloading ist auch ein zweischneidiges Schwert. Nimm zum Beispiel folgenden Code.... da weiß doch kein Mensch mehr was C++ da eigentlich macht
Registriert: Sa Jan 01, 2005 17:11 Beiträge: 2067
Programmiersprache: C++
yunharla hat geschrieben:
Ich persönlich finde using übrigens albern an der Stelle weil C++ ja schließlich auch schon static vergewaltigt und Namespaces ja wirklich etwas komplett anderes sind.... Hätte man sich eher für Module oder so aufsparen sollen.
Jein,
Code:
usingnamespace std;
sagt ja 'nur', dass z.B. std::wstring als wstring erreichbar ist:
Code:
using wstring = std::wstring
Aber gut, bis auf Speziallfälle erlaubt using nichts mehr als typename und es ist nur die umgedrehte Reihenfolge.
@mathias:
Code:
var
i:Integer;
begin
if MyExpression then
begin
DoSomething0();
DoSomething1();
end;
begin
DoSomething0();
DoSomething1();
end;
end;
Es geht um den alleine stehenden Block. Dieser macht in Pascal zwar keinen Sinn, aber in C++ macht er eben wegen RAII viel Sinn und man wird ihn des öfteren finden.
Registriert: Mo Nov 08, 2010 18:41 Beiträge: 769
Programmiersprache: Gestern
i0n0s hat geschrieben:
yunharla hat geschrieben:
Ich persönlich finde using übrigens albern an der Stelle weil C++ ja schließlich auch schon static vergewaltigt und Namespaces ja wirklich etwas komplett anderes sind.... Hätte man sich eher für Module oder so aufsparen sollen.
Jein,
Code:
usingnamespace std;
sagt ja 'nur', dass z.B. std::wstring als wstring erreichbar ist:
Code:
using wstring = std::wstring
Aber gut, bis auf Speziallfälle erlaubt using nichts mehr als typename und es ist nur die umgedrehte Reihenfolge.
Ja genau... ich meine da hätte man doch etwas cooleres machen können. Also zum Beispiel so etwas "with" in VB oder so... Keine Ahnung, ich fand unnötig. Aber hey, choice is always good
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
OpenglerF hat geschrieben:
Mir scheint, du hast immernoch nicht verstanden worauf ich hinaus will: Mir ist klar, dass es in Pascal Kontrollstrukturen gibt, allerdings gibt es weder a) Kontrollstrukturen ohne "end" noch b) Blöcke mit Scope. (den scheint es eh kaum zu geben, wegen funktionsglobaler Variablendefinition)
Zu (a), das ist wenn ich mich jetzt an meine Pascal-Zeiten erinnere, inkorrekt. Folgendes müsste korrekter Code sein:
Code:
if foo then bar;
i0n0s hat geschrieben:
Jein,
Code:
usingnamespace std;
sagt ja 'nur', dass z.B. std::wstring als wstring erreichbar ist:
Code:
using wstring = std::wstring
Aber gut, bis auf Speziallfälle erlaubt using nichts mehr als typename und es ist nur die umgedrehte Reihenfolge.
using ist semantisch äquivalent zu typedef, man kann (seit C++11) auch sowas machen:
Code:
using my_function_type =void(int, int);
yurnharla hat geschrieben:
Naja Operator-Overloading ist auch ein zweischneidiges Schwert. Nimm zum Beispiel folgenden Code.... da weiß doch kein Mensch mehr was C++ da eigentlich macht
Natürlich nicht, du hast ja auch keine Typen für x und y angegeben. Das Verhalten z.B. von ++ hängt auch in C schon vom Typ ab (int* und char* verhalten sich da anders, ersteres macht z.B. +4 und letzteres +1). Es macht halt für den gegebenen Typen etwas sinnvolles – Operatorüberladung ist ein mächtiges Werkzeug, was Code unheimlich viel Lesbarer machen kann.
Das hat man schon nach einer Detour zu Java, wenn man einmal viel mit den BigInteger klassen gemacht hat bekommt man das Kotzen. Da stehen dann Ausdrücke wie (und das ist noch einer der harmlosen):
Code:
BigInteger v = key.y.multiply(key.g.modPow(minus_i, key.p)).mod(key.p);
Anstatt einfach zu schreiben:
Code:
BigInteger v =(key.y* key.g.modPow(minus_i, key.p))% key.p;
grüße, Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Mo Nov 08, 2010 18:41 Beiträge: 769
Programmiersprache: Gestern
ja schon klar, ich finde es auch sehr praktisch. Gerade in unseren Bereich hier wird es ja wohl nur sehr wenige geben die das bestreiten. Aber es steigert nicht unbedingt die Lesbarkeit. Bei C musst du nur den Typen wissen, aber bei C++ musst du halt wissen was der Typ dort eigentlich implementiert. Nimm zum Beispiel mal folgenden Code:
Code:
void do_stuff(vec3_t & dst, vec3_t a, vec3_t b) {
dst = a * b;
}
Man koennte hier ja schliesslich ohne weiteres Kreuzprodukt oder einfache Multiplikation fuer jede Zeile annehmen. Und von irgendwelchen Sachen die Anfaenger dort machen wollen wir mal lieber garnicht erst reden
Da hat wohl jeder schon Sachen gesehen die selbst Objective-C als schoen erscheinen lassen. (obwohl dieser durchaus einen Sinn hat, wenn man bedenkt was das eigentlich macht)
[edit]
Aber ja, das ist nicht unbedingt ein Problem des Syntax an dieser Stelle...
[edit2]
Wenn ihr mal so ein Streithema fuer C erleben wollt: lisp.c
Gut Kommentiert und alles und sehr schoener Code. Nur wer kann das noch lesen?
Naja Operator-Overloading ist auch ein zweischneidiges Schwert. Nimm zum Beispiel folgenden Code.... da weiß doch kein Mensch mehr was C++ da eigentlich macht
Nun, Mathecode ist halt mit Referenztypen ohne Operatorüberladung praktisch unless- und unwartbar. Es mag Bussiness Anwendung geben, da braucht man das nicht, aber zum Beispiel ein Vektor ist in meinen Code etwas so häufiges. Das mit leicht zu entstehenden Seiteneffekten und Methoden nachzubauen, finde ich grauenvoll.
Dein Konstrukt finde ich übrigens nicht unlesbar, höchstens nicht sinnvoll. Und wenn es dir um Operatorüberladungsmissbrauch geht, mal ehrlich, dass mir noch nie begegnet. Das ist doch ein akademisches Problem und besteht genauso ohne Operatorüberladung, wenn man Methoden nicht sinnvoll benennt. Die meist akzeptierte Antwort zu dem Thema hier, finde ich sehr lesenswert: http://stackoverflow.com/questions/77718/why-doesnt-java-offer-operator-overloading
Zitat:
Gut Kommentiert und alles und sehr schoener Code. Nur wer kann das noch lesen?
Ich. Naja. Ich habe keine Ahnung von Lisp und die Formatierung/Einrückung ist bisschen unübersichtlich, und die Namen/Dokumenatation(was zb. macht "ev" oder "in") sind teilweise nicht klar. Das ist aber genauso zum Beispiel auch in Java möglich und hat nix mit C im Speziellen zu tun. Sonst ist das doch normaler und eigentlich gut lesbarer C Code. Wer behauptet das jehenseits der sprachunabhänigen kleinen Komplexität im Code nicht lesen zu können, dem würde ich eher mangelnde Erfahrung mit dem C Syntax unterstellen.
Registriert: Mo Nov 08, 2010 18:41 Beiträge: 769
Programmiersprache: Gestern
Nun ja ich muss hier noch einmal betonen das ich das nicht fuer ein Syntax Problem halte und auch durchaus einen Sinn hinter solchen Features erkenne. Aber ich sag dir ganz ehrlich, wenn ich so einen Code auf Arbeit sehe kriege ich einen Schreikrampf.
Ich bin halt hauptsaechlich in der Wartungsschiene unterwegs und wir haben halt sehr viele Grossprojekte im Bereich Business / Systemsoftware. Sprich ich seh dort wirklich tagtaeglich die Creme de la Creme von "hey ich habe ein neues Feature gelernt, lass es mal einbauen" (gerade erst neulich) oder "schoenen" Code. Und ja, wenn du mal einen Bug in soetwas wie dem Lisp Intepreter suchen sollst, nur eben bei ein paar hundert Dateien mehr an Code.... Viel Spass
In Short: Ich kann die Scheisse wirklich ueberall finden
Achja, und mein Job macht mir uebrigens sehr viel Spass da er unglaublich abwechslungsreich und lustig ist
Btw. fuer alle die gerne C machen wollen und Probleme mit dem Syntax haben. Schaut euch mal das hier an. Dort habt ihr sozusagen die Zusammenfassung von KnR, nur halt vielleicht leichter verstaendlich.
Aber ich sag dir ganz ehrlich, wenn ich so einen Code auf Arbeit sehe kriege ich einen Schreikrampf.
was genau ist schlimmer daran, wenn + multipliziert als wenn .add( multipliziert?
Zitat:
Bei C musst du nur den Typen wissen, aber bei C++ musst du halt wissen was der Typ dort eigentlich implementiert.
musst du bei c auch wissen, nur dass dann dort nicht * steht, sondern multiply oder mulvec oder so was, wovon letzteres insbesondere für generics/templates/macros besonders unlustig ist.
Zitat:
denn konsequent ist meiner Meinung nach nur dann etwas, wenn mehrere gleiche Dinge dem gleichen Syntax folgen.
Wenn gleiche Dinge unterschiedliche Syntax haben, ist das inkonsequent, nicht aber, wenn unterschiedliche Dinge die gleiche Syntax haben, im Gegenteil, das ist durchaus vorteilhaft, sobald du templates/generics/macros verwendest.
Zitat:
Die Syntax von C verwendet vieles wieder, wie man an obigem Beispiel sieht, und ist damit ziemlich Konsequent.
was mir definitiv an c++ besser gefällt als an pascal ist, dass klar ersichtlich ist, welches Argument pass-by-reference und welches pass-by-value ist. Auch suboptimal an pascal ist, dass array als variablendeklaration etwas anderes bedeutet als als Argument, und als Rückgabetyp einer Funktion verboten ist. Und dass array-literals mal mit () geschrieben werden (const), mal mit [] (Argument), und mal verboten sind (überall sonst). Und dass ich eine typdefinition benötige um mehrdimensionale arrays an Funktionen übergeben zu dürfen, oder überhaupt arrays zurückgeben zu dürfen, und die dann aber nicht mehr kompatibel ist mit demselben Typ mit anderem Namen.
Zitat:
Und wie würde Pascal aussehen wenn es eine ähnlich hohe Dynamik erreichen wollte (euer Beispiel mit der For-Schleife).
Ich habe ehrlich gesagt nie verstanden, was überhaupt der Sinn der c for-Schleife ist. Im prinzip nur eine verdrehte while-Schleife.
Zitat:
Eigentlich war C seiner Zeit weit voraus, denn in modernen Skriptsprachen sind untypisierte Parameter wieder "in".
generic != void*
(und int als default für ausgelassene Typbezeichner hat erst recht nichts damit zu tun. weder mit untypisiert noch mit modernen Sprachen)
Registriert: Mo Nov 08, 2010 18:41 Beiträge: 769
Programmiersprache: Gestern
sharkman hat geschrieben:
Zitat:
Aber ich sag dir ganz ehrlich, wenn ich so einen Code auf Arbeit sehe kriege ich einen Schreikrampf.
was genau ist schlimmer daran, wenn + multipliziert als wenn .add( multipliziert?
Aber mal abgesehen von den Missbrauch den ich schon angesprochen haben, ist das ".add" auch sehr viel einfacher zu benutzen und zu erstellen. Postfix-Ausdrücke haben nämlich die höchste Wertigkeit (gleich nach Konstanten und Klammern) und werden daher immer zuerst ausgeführt. Es gibt also erst gar keine Verwirrung oder Streitigkeiten über die Reihenfolge oder aber solche Argumente gegen Implizite Funktionsweisen wie etwa bei Casts oder Constructor. Wenn du also nicht gerade eine Matheklasse, Collection oder so einen Kram baust sollte man es lieber sein lassen. Zumindest sollte man nicht wie Cout einfach irgendwas aus der Mitte greifen nur weil es vielleicht cool aussieht oder so.
sharkman hat geschrieben:
Zitat:
Bei C musst du nur den Typen wissen, aber bei C++ musst du halt wissen was der Typ dort eigentlich implementiert.
musst du bei c auch wissen, nur dass dann dort nicht * steht, sondern multiply oder mulvec oder so was, wovon letzteres insbesondere für generics/templates/macros besonders unlustig ist.
Nein, das würde man nicht, sondern CrossProduct und DotProduct oder XPD, DP3 und MUL oder so etwas
sharkman hat geschrieben:
Zitat:
Und wie würde Pascal aussehen wenn es eine ähnlich hohe Dynamik erreichen wollte (euer Beispiel mit der For-Schleife).
Ich habe ehrlich gesagt nie verstanden, was überhaupt der Sinn der c for-Schleife ist. Im prinzip nur eine verdrehte while-Schleife.
ich denke mal du spielst jetzt hier auf das "for ... to..." bzw. "for ... downto ..." an oder? Falls ja, das hängt mit dem nächsten Punkt zusammen. Man will halt mehr als Integrale-Typen verarbeiten.
sharkman hat geschrieben:
Zitat:
Eigentlich war C seiner Zeit weit voraus, denn in modernen Skriptsprachen sind untypisierte Parameter wieder "in".
generic != void*
(und int als default für ausgelassene Typbezeichner hat erst recht nichts damit zu tun. weder mit untypisiert noch mit modernen Sprachen)
Wie ich bereits sagte, das ist Legacy-Kram. Früher war halt das Hardware-Word der einzige Datentyp den es gab (mal abgesehen von Spezialfällen). Floating Point und Single-Byte kamen halt erst später dazu. Ich finde es aber durchaus bemerkenswert das wir heute wieder solche alten Sachen wiederentdecken und feststellen das es hier und dort cool ist.
Registriert: So Aug 08, 2010 08:37 Beiträge: 460
Programmiersprache: C / C++ / Lua
Zitat:
Und wie würde Pascal aussehen wenn es eine ähnlich hohe Dynamik erreichen wollte (euer Beispiel mit der For-Schleife). Ich habe ehrlich gesagt nie verstanden, was überhaupt der Sinn der c for-Schleife ist. Im prinzip nur eine verdrehte while-Schleife.
Die for Schleife in C-artigen Sprachen ist wesentlich flexibler als in Pascal. Das Gegenteil ist der Fall, die while Schleife ist eine simplere Form der for Schleife (um Horazont zu zitieren:
Code:
#define while (x) for (;x;)
)
Man kann diverse Sachen mit C-artigen for Schleifen machen, die in Pascal nur mit mehreren Schleifen moeglich sind. Horazont hatte letztens im IRC da ein sehr nettes Beispiel.
Zitat:
Nun ja ich muss hier noch einmal betonen das ich das nicht fuer ein Syntax Problem halte und auch durchaus einen Sinn hinter solchen Features erkenne. Aber ich sag dir ganz ehrlich, wenn ich so einen Code auf Arbeit sehe kriege ich einen Schreikrampf.
Ich wuerde auch einen Schreikrampf kriegen, aber nicht, weil Operator Overloading benutzt wurde, sondern weil der Code offensichtlich obfuscated wurde (mit purer Absicht).
Operator Overloading oder andere C++ Features kann man sinnvoll einsetzen und falls man mal nicht weiss, was gemeint ist, sollte es bei grossen Projekten eine Dokumentation geben. Das ist wenn dann kein Sprach- oder Syntaxproblem sondern einfach das uebliche Problem von schlechtem Stil / schlechten Programmierern, die nicht dokumentieren, etc.
_________________ offizieller DGL Compliance Beauftragter Never run a changing system! (oder so)
Registriert: Mo Nov 08, 2010 18:41 Beiträge: 769
Programmiersprache: Gestern
end hat geschrieben:
Ich wuerde auch einen Schreikrampf kriegen, aber nicht, weil Operator Overloading benutzt wurde, sondern weil der Code offensichtlich obfuscated wurde (mit purer Absicht).
Operator Overloading oder andere C++ Features kann man sinnvoll einsetzen und falls man mal nicht weiss, was gemeint ist, sollte es bei grossen Projekten eine Dokumentation geben. Das ist wenn dann kein Sprach- oder Syntaxproblem sondern einfach das uebliche Problem von schlechtem Stil / schlechten Programmierern, die nicht dokumentieren, etc.
Bezog sich auch ganz eindeutig darauf, sonst hätte ich ja nicht das Beispiel mit dem Interpreter gebracht
Mitglieder in diesem Forum: 0 Mitglieder und 62 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.