Hallo,
bisher habe ich mich in C-Code immer ganz gut zurecht gefunden. Bis
heute ;-)
Was zum Teufel macht das Komma und der hintere Teil da?
double const v = mReader->GetValue(offset), lastValue = mLastValue;
Ich würde sagen das ist C++ :-)
Es werdem die konstanten double Variablen v und lastValue deklariert und
diese bekommen gleich Werte zugewiesen.
lastValue bekommt den Wert von mLastValue zugewiesen und v bekommt den
Rückgabewert der Funktion GetValue(offset), die in einer hier nicht
bekannten Klasse definiert ist bzw durch die Instanz mReader der Klasse
instanziiert wurde.
cpp schrieb:> Ich würde sagen das ist C++ :-)> Es werdem die konstanten double Variablen v und lastValue deklariert und> diese bekommen gleich Werte zugewiesen.> lastValue bekommt den Wert von mLastValue zugewiesen und v bekommt den> Rückgabewert der Funktion GetValue(offset), die in einer hier nicht> bekannten Klasse definiert ist bzw durch die Instanz mReader der Klasse> instanziiert wurde.
Ja, hast du recht. hab ich direkt überlesen, weils den Pfeiloperator ja
in C auch gibt. Ist hier aber eindeutig C++ mit Klassen etc.
Ruppelbutz schrieb:> bisher habe ich mich in C-Code immer ganz gut zurecht gefunden. Bis> heute ;-)
C ist eine von den Sprachen, wo es eine Ehre sein kann, etwas nicht zu
koennen... ganz einfach weil es ein Hinweis darauf ist, dass du im
Praxisalltag gewisse Dinge, die in C zwar moeglich aber selten guter
Stil sind, nicht tust. :-)
cybmorg schrieb:> C ist eine von den Sprachen, wo es eine Ehre sein kann, etwas nicht zu> koennen... ganz einfach weil es ein Hinweis darauf ist, dass du im> Praxisalltag gewisse Dinge, die in C zwar moeglich aber selten guter> Stil sind, nicht tust. :-)
Aber mehrere durch Komma getrennte Deklaratoren in einer Deklaration
sind doch kein schlechter Stil. Dasselbe gilt für Initialisierungen.
Die Sache mit dem Funktionszeiger scheint der TE ja noch verstanden zu
haben, erst ab dem Komma kamen die Probleme:
Ruppelbutz schrieb:> Was zum Teufel macht das Komma und der hintere Teil da?
Wie auch immer, jetzt hat er's ja gerafft :-)
Jonas K. schrieb:> Ich hätte gedacht, ein aufruf von Zeiger auf Funktionen müsste so> ausschauen?
Man kann bei Funktionszeigern den Stern schreiben oder weglassen.
Dass der Zeiger dereferenziert wird (statt nur als Zeigerwert
weitergegeben), ergibt sich bereits eindeutig aus den anschließenden
runden Klammern.
Andreas schrieb:> Das gilt aber ganz sicher nicht für Pointer auf Funktionen!
Darauf habe ich mich auch nicht bezogen, sondern auf die urspruengliche
Frage des Posters. Diese Art die Deklaration und Initialisierung von
mehreren Variablen in eine Zeile zu quetschen, nur weil sie den gleichen
Typ haben ist meist so ueberfluessig wie unleserlich.
Bei der ursprüngliche Sprachstruktur von C ist innerhalb von Ausdrücken
der Name einer Funktion implizit ein Pointer auf diese Funktion. In
void f(void);
void (*p)(void);
sind sowohl "f" als auch "p" Pointer auf Funktionen. "f()" und "p()"
sind folglich eine Dereferenzierung dieser Pointer.
Dass man neben "... = f;" und "p()" auch "... = &f;" und "(*p)()"
schreiben kann ist strukturell unlogisch. Es ist eine Konzession an
jene, die das ursprüngliche Konzept verwirrt hat.
Yalu X. schrieb:> Aber mehrere durch Komma getrennte Deklaratoren in einer Deklaration> sind doch kein schlechter Stil. Dasselbe gilt für Initialisierungen.
Was ist denn der Vorteil davon? Dass ein paar Zeilen gespart werden? Und
dafuer stehen Variablendeklarationen, deren einzige gemeinsame Beziehung
der gleiche Typ ist auf einer Zeile?
Aber die Diskussion ist sinnlos - fuer viele alte C-Hacker geht
Kompaktheit immer vor Lesbarkeit. Es ist eine Frage von wenigen Posts,
bis die ersten elitaeren Sprueche kommen...
Der Komma-Operator in Ausdrücken ist/war im Zusammenhang mit
Präprozessor-Macros notwendig. Als es noch keine Inline-Funktionen gab,
war etwas wie getc() anders nicht effizient implementierbar.
Im Statement des TO ist der freilich nicht wirklich angebracht.
A. K. schrieb:> Im Statement des TO ist der freilich nicht wirklich angebracht.
Naja, dort ist es aber kein Komma-Operator, sondern das
Aufzählungskomma in einer Variablendefinition. =:-)
Ansonsten bekäme "v" ja den Wert von "lastValue", nicht den, den
mReader->GetValue() zurückgibt. Beim Kommaoperator ist schließlich
der Teilausdruck links des Kommas nur zu bewerten, trägt aber nicht
zum Resultat bei.
Jörg Wunsch schrieb:> Naja, dort ist es aber kein Komma-Operator, sondern das> Aufzählungskomma in einer Variablendefinition. =:-)
Hehe, stimmt.
Wobei das Komma in Definitionen sich in for-Statements gelegentlich
nützlich macht. Seit die dort zulässig sind.
A. K. schrieb:> In> void f(void);> void (*p)(void);> sind sowohl "f" als auch "p" Pointer auf Funktionen.
Vorsicht: Ähnlich, wie ein Array nicht das Gleiche wie ein Pointer auf
sein erstes Element ist, ist auch eine Funktion nicht das Gleiche wie
ein Pointer auf diese Funktion.
Der Unterschied wird klar, wenn man nach der Zuweisung p = f den
&-Operator auf f und p anwendet. Sowohl der Typ als auch der numerische
Inhalt von &f und &p sind verschieden.
Dafür ist aber f das Gleiche wie *****f und *******p (Anzahl der * ist
beliebig), was bei Arrays in entsprechender Weise nicht gilt.
Yalu X. schrieb:> Der Unterschied wird klar, wenn man nach der Zuweisung p = f den> &-Operator auf f und p anwendet.
Das liegt an der erwähnten Inkonsequenz durch 2 verschiedene
gleichzeitig zulässige jeweils nur in sich konsistenter Schemata:
(1) p = f; p(); f();
(2) p = &f; (*p)(); f();
Innerhalb von (1) ist in Ausdrücken
f
ein Pointer, also die Adresse der Funktion,
f()
die Dereferenzierung eines Pointers und
&f;
ist undefiniert, weil das vergleichbar ist zu
&1;
Innerhalb von (2) ist in Ausdrücken
f
eine Funktion, nicht deren Adresse,
f()
keine Dereferenzierung, und
f;
p = f;
ist undefiniert, liesse sich aber als Aufruf ohne Parameter verstehen,
wie in anderen Sprachen realisiert.
Da kein Konflikt zwischen (1) und (2) entsteht konnte man beides
gleichermassen zulassen. Aber dadurch gibts eben ein paar merkwürdige
Effekte, wenn man anfängt, drüber nachzudenken, und wenn man beide
Schemata mischt.
Ich gehe davon aus, dass es zunächst nur (1) gab und (2) später hinzu
kam, weil manchen (1) nicht verständlich war.
A. K. schrieb:> Das liegt an der erwähnten Inkonsequenz durch 2 verschiedene> gleichzeitig zulässige jeweils nur in sich konsistenter Schemata:
Diese Inkonsistenz verschwindet, wenn man statt der beiden von dir
vorgeschlagenen Schemata folgende drei Auswerteregeln anwendet, die
denen für Arrays ähnlich sind und die im Wesentlichen den neueren
C-Standards entsprechen:
1. Ein Ausdruck, der eine Funktion liefert, wird durch einen Pointer auf
diese Funktion ersetzt, es sei denn, der Ausdruck ist Argument des
sizeof- oder des Adressoperators. In diesem Fall bleibt der Ausdruck
unverändert.
2. Der sizeof-Operator auf eine Funktion angewendet ist ein Fehler¹.
3. Ein Funktionspointer mit nachfolgender eingeklammerter Argumentliste
bewirkt einen Aufruf der Funktion, auf die der Pointer zeigt.
Damit sind alle diese Fälle in konsistenter Weise abgedeckt:
> (1) p = f; p(); f();> (2) p = &f; (*p)(); f();> Ich gehe davon aus, dass es zunächst nur (1) gab und (2) später hinzu> kam, weil manchen (1) nicht verständlich war.
Wenn man im "C Reference Manual" von Dennis Ritchie die entsprechenden
Informationen zusammenträgt, sind folgende Anweisungen
1
f();/* klar */
2
p=f;/* "function returning ..." wird in "pointer to function returning ..." konvertiert */
p=&f;/* der Adressoperator war damals nur für lvalues zugelassen, f ist aber keiner */
2
p();/* p ist nicht vom Typ "function returning ..." */
Es passt also keines der beiden von dir genannten Schemata.
———————————
¹) Der GCC erweitert die Definition von sizeof dahingehend, dass sie bei
der Anwendung auf eine Funktion den Wert 1 liefert.
Yalu X. schrieb:> Damit sind alle diese Fälle in konsistenter Weise abgedeckt:
Konsistent geht für mich anders, wenn &f gerne mal das gleiche ist wie
f, und *p das gleiche wie p. Ich sehe das eher als Regelsatz für "naja
ok, es funktioniert so irgendwie". ;-)
> Wenn man im "C Reference Manual" von Dennis Ritchie die entsprechenden> Informationen zusammenträgt, sind folgende Anweisungen
Stimmt. Leider. Ok, viel Sinn für innere Logik konnte man Ritchie
ohnehin nicht vorwerfen.
Wirth über C: "It is indeed absolutely surprising with which eqanimity
this notational monster was accepted by the world-wide programmer’s
community."
Bastler schrieb:> Wobei der liebe Nikolaus natürlich ganz objektiv über seine Mitbewerber> geurteilt hat ;-)
Angesichts dessen, dass der Dicke mit "o" immer noch überall rumspringt,
und farblich grosse Ähnlichkeit mit der Schweizer Fahne aufweist, sei
dir die Verwechselung verziehen. ;-)
Der ist anders gewickelt. Prof eben, mit Sinn für sprachliche Ästhetik,
kein Wirtschaftler. C++ hat das ganze dann quadriert, da hatten sich mir
nach Lektüre von Stroustrups Werk stellenweise die Zehennägel
gekräuselt.
A. K. schrieb:> Prof eben, mit Sinn für sprachliche Ästhetik,> kein Wirtschaftler.
Nur hat er in seinem Konstrukt "Pascal" Dinge drin, die mit Pascal
selbst nicht erzeugt werden können -- variadische Funktionen nämlich.
Eine Funktion wie write oder writeln kann man in Pascal selbst nicht
schreiben.
Deshalb sah das in späteren Werken ja auch anders aus. Wenn man Sprachen
schafft, die nicht so einschlagen wie C, hat man gewisse Freiheiten, es
das nächste Mal besser zu machen.
A. K. schrieb:> Wenn man Sprachen schafft, die nicht so einschlagen wie C, hat man> gewisse Freiheiten, es das nächste Mal besser zu machen.
So ist es.
Irgendjemand (vielleicht war es sogar jemand hier im Forum) hat einen
Spruch ähnlich dem folgenden geprägt:
1
Es gibt zwei Sorten von Programmiersprachen:
2
Solche, die unsauber sind, und solche, die keiner benutzt.
A. K. schrieb:> Wirth über C: "It is indeed absolutely surprising with which eqanimity> this notational monster was accepted by the world-wide programmer’s> community."
Tja, in jeder Sprache gibt es Ungereimtheiten.
Im Englischen gibt es "the",
im Deutschen "der, die , das".
Wo ist das Problem ? Lerne die Sprache, benutze Sie und vergewaltige Sie
nicht, wie 'Ihr da oben tut.
Just my cent
P.S: was ist denn die tolle Sprache ohne Fehler ?
Yalu X. schrieb:> A. K. schrieb:>> Wenn man Sprachen schafft, die nicht so einschlagen wie C, hat man>> gewisse Freiheiten, es das nächste Mal besser zu machen.>> So ist es.>> Irgendjemand (vielleicht war es sogar jemand hier im Forum) hat einen> Spruch ähnlich dem folgenden geprägt:> Es gibt zwei Sorten von Programmiersprachen:> Solche, die unsauber sind, und solche, die keiner benutzt.
Das stammt von Stroustrup (Erfinder von C++).
1
There are only two kinds of programming languages:
2
Those people always bitch about and those nobody uses.
Hallo zusammen,
Ich lese den Thread, da ich gerade auch weiter in die Programmierung in
C ensteigen möchte. Daher bleibt einem der Umgang mit Pointern natürlich
nicht erspart. Gerade bei Ringpuffern möchte ich ohne Pointer gar nicht
mehr auskommen.
Das man einem Pointer eine Funktion zuweist ist mehr noch recht neu und
daher stelle ich mal ganz dumm die Frage: Welchen grossen Vorteil hat
man da? Zuerst habe ich ja mal mehr "arbeit". Ich muss einen Pointer
anlegen, ihm die Funktion bzw Adresse der Funktion zuweisen und erst
dann kann ich die Funktion aufrufen. Also ich sehe darin gerade keinen
Vorteil aber es gibt ihn oder vielleicht sogar mehrere.
>Also ich sehe darin gerade keinen>Vorteil aber es gibt ihn oder vielleicht sogar mehrere.
Es gibt mehrere Vorteile:
Man kann die Pointer in Arrays oder Hashtables packen und
einfach über den Index bzw. Key die Funktionen aufrufen
ohne lange if oder switch Anweisungen schreiben zu müssen.
Die Funktions Pointer in Arrays und Hashtables kann man
natürlich auch zur der Laufzeit ändern.
Beim Laden von DLLs zur Laufzeit benötigt man Funktions Pointer
umd die Funktionen in der DLL aufzurufen.
Andreas.
Hans schrieb:> Das stammt von Stroustrup (Erfinder von C++).>> There are only two kinds of programming languages:> Those people always bitch about and those nobody uses.> :)
Klasse! Genau danach hatte ich gesucht, aber nichts gefunden, weil ich
mich weder an den genauen Wortlaut noch an den Autor, ja, nicht einmal
an die Sprache (Englisch/Deutsch) erinnerte.
@Peter:
Eine weitere Anwendung für Funktionszeiger:
http://de.wikipedia.org/wiki/Callback-Funktion