bei der deklaration eines funktionszeigers
int (*tuWas)(char *, char *);
ist die logik ja, bei tuWas anzufangen und sich dann von innen nach
aussen zu hangeln. Also tuWas ist ein zeiger auf eine funktion die zwei
zeiger auf char erwartet und int ausgibt.
möchte man diesen funktionspointer casten wuerde das beispielsweise so
(int (*)(void*,void*))tuWas
aussehen. hier ist mir nicht wirklich klar, wo man im cast anzufangen
hat zu lesen... irgendwie muesste das ja beim ersten stern anfangen.
Also caste auf einen zeiger auf eine funktion die zwei void zeiger
erwartet und int ausgibt. ich kann mir das zwar denken, aber woher weiss
das der compiler?? mich interessiert also die logik, die dahinterliegt.
weiss einer von euch mehr? (oder kann mich auf eine gut erklärende
quelle verweisen?)
und warum muss der erste stern im cast geklammert werden?
dankö
sina anargo schrieb:> bei der deklaration eines funktionszeigers>> aussehen. hier ist mir nicht wirklich klar, wo man im cast anzufangen> hat zu lesen...
genau gleich.
Nimm deine erste Erklärung her, lass alle Variablen-Namen weg, und du
landest beim gesuchten Cast.
> Also caste auf einen zeiger auf eine funktion die zwei void zeiger> erwartet und int ausgibt. ich kann mir das zwar denken, aber woher weiss> das der compiler?? mich interessiert also die logik, die dahinterliegt.> weiss einer von euch mehr? (oder kann mich auf eine gut erklärende> quelle verweisen?)
Allerdings:
* gerade bei Funktionszeigerm kann man sich mit ein paar typedef das
Leben als Programmierer signifikant einfacher machen.
* Funktionszeiger zu casten ist eine problematische Sache. Wenn man
weiß, was man tut, und zb abhängig von einem Typ-Flag den cast
durchführt, ist es in Ordnung. Aber abgesehen von diesem Fall, muss man
sich allerdings der Frage stellen: Warum muss man da überhaupt casten
und wäre eine union nicht die bessere Lösung gewesen?
> und warum muss der erste stern im cast geklammert werden?
Musste er ja hier auch
1
int(*tuWas)(char*,char*);
der * beim 'tuWas' ist ja auch in der Klammer. Und der muss dort auch
sein, dann sonst würde es sich ja um einen Funktionsprototypen handeln,
für eine Funktion tuWas, die zwei char-Pointer übernimmt und einen
int-Pointer liefert.
Karl Heinz schrieb:> Warum muss man da überhaupt casten und wäre eine union nicht die bessere> Lösung gewesen?
Ansonsten immer im Hinterkopf behalten: ein Cast zwischen Objekt- und
Funktionszeigern ist durch den C-Standard nicht gedeckt. Es dürfen
nur Objektzeiger beliebig von einem konkreten (typisierten) Zeiger auf
void * (und aus historischen Gründen auch auf char *) sowie wieder
zurück auf den konkreten Zeiger gewandelt werden sowie Funktionszeiger
in einen anderen Funktionszeiger.
Wenn man also einen generischen Funktionszeiger braucht, dann kann man
sich mit sowas behelfen (wenn die Union aus irgendeinem Grunde nicht
sinnvoll passt):
Jörg Wunsch schrieb:> Ansonsten immer im Hinterkopf behalten: ein Cast zwischen Objekt- und> Funktionszeigern ist durch den C-Standard nicht gedeckt.
Unter POSIX-Systemen allerdings schon, denn dort braucht man zB zur
Verwendung von dlsym() den Cast zwischen Objekt&Funktions-Zeiger...
dazu merke ich mir noch wieviele argn dabei sind
also in die Queue kommen der FP , anzahl argn , und die argn
der aufruf erfolgt in abhängigkeit von der anzahl argn
Dr. Sommer schrieb:> Unter POSIX-Systemen allerdings schon, denn dort braucht man zB zur> Verwendung von dlsym() den Cast zwischen Objekt&Funktions-Zeiger...
Wobei die Rationale zu dlsym() das Dilemma vermerkt und ggf. über die
Einführung einer künftigen Alternative spricht:
http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html
Ein typisches Beispiel für eine Architektur, bei der ein Objektzeiger
ggf. nicht in der Lage ist, einen Funktionszeiger aufzunehmen, ist
übrigens der AVR (auf den Modellen mit mehr als 128 KiB Flash).
Karl Heinz schrieb:>> und warum muss der erste stern im cast geklammert werden?>> Musste er ja hier auch int (*tuWas)(char *, char *);
hier versteh ich ja die klammer um (*tuWas), weil es bei tuWas los geht
und dann anstatt rechts weiter zu lesen, erstmal der stern links
ausgewertet werden soll.
beim cast
int (*)(char *, char *)
gehts ja anscheinend schon beim ersten stern los... da brauch man doch
den stern nicht mehr klammern... oder es geht rechts vom stern los...
woher weiss der compiler das dann? irgendwie fehlt mir der
"einstiegspunkt" ohne einen bezeichner wie tuWas... würd gern die
dahinterliegende logik verstehen.
das mit der union kenn ich noch nicht. könnt ihr mir mal ein kurzes
beispiel geben?
vielen dank schonmal fuer die vielen antworten
lg
sina anargo schrieb:>> das mit der union kenn ich noch nicht. könnt ihr mir mal ein kurzes> beispiel geben?>>> vielen dank schonmal fuer die vielen antworten>> lg
Also ich habe es auch erst verstanden, als es eine sinnvolle Anwendung
dafuer gab.
1
union_8080_sp
2
{
3
struct_8080_sp_hl
4
{
5
unsignedcharh;
6
unsignedcharl;
7
}hl8;
8
unsignedinthl16;
9
}sp_8080,pc_8080,offset_8080;
Die Syntax ist ganz C maessig etwas rueckwaerts, also z.B. der Name der
Union _8080_sp wird garnicht verwendet.
Was ich hier konkret tue ist 3 Veriablen zu definieren:
sp_8080, pc_8080, und offset_8080.
Bei diesen koennen die oberen und unteren 8 bits hl8.h und hl8.l
unabhaengig als uchar angesprochen werden.
sogleich wird auch hl16, uint, welche mit hl8 eine "union" bildet, den
richtigen 16bit (uint) Wert enthalten!
Was ist der Sinn des ganzen? Man kann sich langatmige Typcasts sparen,
wenn z.b. ein uint Offset als 2 8bit Werte aus dem Speicher geladen
werden soll. Hierbei soll die Reihenfolge durch das Programm vorgegeben
werden. Ausserdem ist es auch erfoderlich, auf das obere und untere Byte
direkt zuzugreifen.
Also
sina anargo schrieb:> beim cast>> int (*)(char *, char *)>> gehts ja anscheinend schon beim ersten stern los... da brauch man doch> den stern nicht mehr klammern... oder es geht rechts vom stern los...> woher weiss der compiler das dann? irgendwie fehlt mir der> "einstiegspunkt" ohne einen bezeichner wie tuWas... würd gern die> dahinterliegende logik verstehen.
Die Logik ist ganz einfach:
Nimm eine entsprechende Definition einer Variablen und lass die Namen
weg.
Im Prinzip könnte man das in diesem speziellen Fall auch ohne die
Klammern erkennen, denn
1
int*(char*,char*)
ist keine gültige C Datentypbezeichnung.
Aber: Das wäre dann schon wieder ein Sonderfall. So hast du eine
einfache Regel. Ein Cast sieht aus wie die Definition einer Variablen,
wobei man den Variablennamen weglässt. Das ist einfach zu merken und
einfach anzuwenden. Jeder der eine Variable korrekt definieren kann,
kann damit auch einen Cast anschreiben, der einen Ausdruck in den
Datentyp dieser Variablen casten kann (falls das überhaupt möglich ist).
> das mit der union kenn ich noch nicht. könnt ihr mir mal ein kurzes> beispiel geben?
Vorteil ist, dass du dir nicht einfach irgendwas zurecht casten kannst,
wie du lustig bist. Solange die 'Kennzahlen' für den Funktionstyp bei
der Zuweisung und der Auswertung übereinstimmen, hast du dich wieder
soweit in den sicheren Hafen manövriert, als du dem Compiler wenigstens
ein rudimentäres Überprüfen der Datentypen ermöglichst.
Ein Cast hingegen ist ein effektives Abschalten dieser Überprüfung. Und
die Praxis zeigt, dass das öfter als einem lieb ist schon auch mal ins
Auge geht. Das Vertrauen in die Fähigkeiten des Programmierers war beim
alten K&R C noch recht ausgeprägt, wurde dann aber ganz schnell immer
weiter zurückgedrängt, als sich herausgestellt hat, dass dieses
Vertrauen nicht unbedingt etwas ist, worauf man sichere Programme setzen
soll. Vertrauen ist gut, Kontrolle ist besser.
sina anargo schrieb:> da brauch man doch den stern nicht mehr klammern
Doch, ansonsten erzeugst du einen Zeiger auf "int", nicht einen Zeiger
auf eine Funktion, die "int" zurückgibt.
> das mit der union kenn ich noch nicht. könnt ihr mir mal ein kurzes> beispiel geben?
Also soweit ich es verstehe, verwenden (Sie?) verwendest du eine union,
um mit unterschiedlichen Datentypen umgehen zu koennen (hier:
Funktionszeiger).
Wenn dann auf einen anderen in der union vorhandenen Typ zugegriffen
wird macht es natuerlich keinen Sinn. Also es wird immer nur ein
bestimmer verwendet, und der ist auswaehlbar. Diese Selektion wird in
einer numerischen Variablen vermerkt.
Mal richtig was gelernt heute. Habe ich so nicht gesehen online, union
habe ich mehrfach schon nachgelesen aber noch keine sinvolle Anwendung
dafuer gefunden (bis vor kurzem).
Takao K. schrieb:> Also soweit ich es verstehe, verwenden (Sie?) verwendest du eine union,> um mit unterschiedlichen Datentypen umgehen zu koennen (hier:> Funktionszeiger).
Ich verwende eine union um vom Prinzip her nur eine einzige Variable zu
haben, die ja nachdem wie ich sie anspreche, einen anderen Datentyp hat.
> Wenn dann auf einen anderen in der union vorhandenen Typ zugegriffen> wird macht es natuerlich keinen Sinn.
Und ist offziell auch verboten.
> Also es wird immer nur ein> bestimmer verwendet, und der ist auswaehlbar. Diese Selektion wird in> einer numerischen Variablen vermerkt.
Genau.
Der springende Punkt ist, dass ich in der Verwendung dann nicht einfach
caste, wie es mir in den Sinn kommt, sondern das das Typsystem der
Sprache nach wie vor für mich arbeitet. Solange es keinen Wurschtel mit
den Kennzahlen gibt. Und den kann ich mit Funktionen so einigermassen
unter Kontrolle halten (na ja).
> Mal richtig was gelernt heute. Habe ich so nicht gesehen online, union> habe ich mehrfach schon nachgelesen aber noch keine sinvolle Anwendung> dafuer gefunden (bis vor kurzem).