Hallo Zusammen, leider weiß ich nicht wie ich das hier am besten caste, hat jemand nen Tip, oder ne Quelle zum nachlesen? void ausgabe (char *Var, void *Val) { fprintf (stdout, ">%s<\n>%s<\n", Var, Val); } Danke Daniel
On Mon, 2005-10-17 at 08:43 +0200, Daniel Bauer wrote:
Hallo Zusammen,
leider weiß ich nicht wie ich das hier am besten caste, hat jemand nen Tip, oder ne Quelle zum nachlesen? man 3 printf
void ausgabe (char *Var, void *Val) { fprintf (stdout, ">%s<\n>%s<\n", Var, Val); } Worin besteht dein Problem?
Du willst einen "void*" nach stdout ausgeben? Einen void* als %s auszugeben macht keinen Sinn. %s ist nur für char* definiert. Die entscheidende Frage wäre: Als was willst Du den "void*" ausgeben? Ich nehme mal an, Du suchst %p. Ralf
From: "Ralf Corsepius"
On Mon, 2005-10-17 at 08:43 +0200, Daniel Bauer wrote:
leider weiß ich nicht wie ich das hier am besten caste, hat jemand nen Tip, oder ne Quelle zum nachlesen? man 3 printf
void ausgabe (char *Var, void *Val) { fprintf (stdout, ">%s<\n>%s<\n", Var, Val); } Worin besteht dein Problem?
Du willst einen "void*" nach stdout ausgeben? Einen void* als %s auszugeben macht keinen Sinn. %s ist nur für char* definiert.
Die entscheidende Frage wäre: Als was willst Du den "void*" ausgeben?
Ich nehme mal an, Du suchst %p.
Hallo Ralf, nein, es ist so richtig wie's dasteht, mein Problem ist, daß ich mir variablen Funktionen und Parametern arbeite. Ich habe einen "Würgaround" geschafft, indem ich das ganze wie unten gelöst habe, hatte aber die Hoffnung auf diesen Umweg durch richtiges casten verzichten zu können. void ausgabe (char *Var, void *Val) { char *Str; Str = Val; fprintf (stdout, ">%s<\n>%s<\n", Var, Str); } Danke und Gruß Daniel
On Mon, 2005-10-17 at 10:04 +0200, Daniel Bauer wrote:
From: "Ralf Corsepius"
On Mon, 2005-10-17 at 08:43 +0200, Daniel Bauer wrote:
leider weiß ich nicht wie ich das hier am besten caste, hat jemand nen Tip, oder ne Quelle zum nachlesen? man 3 printf
void ausgabe (char *Var, void *Val) { fprintf (stdout, ">%s<\n>%s<\n", Var, Val); } Worin besteht dein Problem?
Du willst einen "void*" nach stdout ausgeben? Einen void* als %s auszugeben macht keinen Sinn. %s ist nur für char* definiert.
Die entscheidende Frage wäre: Als was willst Du den "void*" ausgeben?
Ich nehme mal an, Du suchst %p.
Hallo Ralf,
nein, es ist so richtig wie's dasteht, Dem ist nicht so. Dein Code ist fehlerhaft, falsch und, schlimmer noch ein Sicherheitsrisiko.
mein Problem ist, daß ich mir variablen Funktionen und Parametern arbeite. Keine Ahnung was Du unter variablen Funktionen und variablen Parametern verstehst, Funktionen mit variablen Argumentlisten werden heutzutage üblicherweise mittels
verarbeitet.
Sie mittels void* zu ersetzen zu wollen ist schlichtweg unsauber.
Ich habe einen "Würgaround" geschafft, indem ich das ganze wie unten gelöst habe, hatte aber die Hoffnung auf diesen Umweg durch richtiges casten verzichten zu können.
void ausgabe (char *Var, void *Val) { char *Str; Str = Val; fprintf (stdout, ">%s<\n>%s<\n", Var, Str); } Ein übler Hack - Ich kann nur davon abraten, weil es keinen Zusammenhang zwischen \0-terminierten c-Strings (Nur solche kann printf verarbeiten) und void* gibt.
Wenn deine "void*" \0-terminierte c-Strings sind, solltest Du sie auch als solche an diese Funktion übergeben. Und wenn schon casten (Wovon ich mit Nachdruck abrate), dann besser unmittelbar im Funktionsaufruf. Noch weiterausgeholt, generell sollten sich derartige Casts immer vermeiden lassen. Erscheinen sie als unvermeidbar, deutet das auf ein Problem in deinem Code hin (Falsch gewählter Typ). Ralf
From: "Ralf Corsepius"
On Mon, 2005-10-17 at 10:04 +0200, Daniel Bauer wrote:
From: "Ralf Corsepius"
On Mon, 2005-10-17 at 08:43 +0200, Daniel Bauer wrote:
leider weiß ich nicht wie ich das hier am besten caste, hat jemand nen Tip, oder ne Quelle zum nachlesen? man 3 printf
void ausgabe (char *Var, void *Val) { fprintf (stdout, ">%s<\n>%s<\n", Var, Val); } Worin besteht dein Problem?
Du willst einen "void*" nach stdout ausgeben? Einen void* als %s auszugeben macht keinen Sinn. %s ist nur für char* definiert.
Die entscheidende Frage wäre: Als was willst Du den "void*" ausgeben?
Ich nehme mal an, Du suchst %p.
nein, es ist so richtig wie's dasteht, Dem ist nicht so. Dein Code ist fehlerhaft, falsch und, schlimmer noch ein Sicherheitsrisiko.
mein Problem ist, daß ich mir variablen Funktionen und Parametern arbeite. Keine Ahnung was Du unter variablen Funktionen und variablen Parametern verstehst, Funktionen mit variablen Argumentlisten werden heutzutage üblicherweise mittels
verarbeitet. Sie mittels void* zu ersetzen zu wollen ist schlichtweg unsauber.
Ich habe einen "Würgaround" geschafft, indem ich das ganze wie unten gelöst habe, hatte aber die Hoffnung auf diesen Umweg durch richtiges casten verzichten zu können.
void ausgabe (char *Var, void *Val) { char *Str; Str = Val; fprintf (stdout, ">%s<\n>%s<\n", Var, Str); } Ein übler Hack - Ich kann nur davon abraten, weil es keinen Zusammenhang zwischen \0-terminierten c-Strings (Nur solche kann printf verarbeiten) und void* gibt.
Wenn deine "void*" \0-terminierte c-Strings sind, solltest Du sie auch als solche an diese Funktion übergeben. Und wenn schon casten (Wovon ich mit Nachdruck abrate), dann besser unmittelbar im Funktionsaufruf.
Noch weiterausgeholt, generell sollten sich derartige Casts immer vermeiden lassen. Erscheinen sie als unvermeidbar, deutet das auf ein Problem in deinem Code hin (Falsch gewählter Typ).
Hallo Ralf, ich finde Deine Aussage "das alles falsch ist" - ohne den kompletten Projektbereich zu kennen - etwas heftig. Einfach gesagt: es geht darum das mein Programm sich eines Webservers bedient und dessen Ein- und Ausgaben steuert/empfängt. Zum Aufbau des HTML Codes benutze ich eine Funktionstabelle die mit div. Parametern gefüttert und zur Ausgabezeit angesprochen wird. Da in dieser Funktion alle Arten (char, int, long, double) verarbeitet werden, setze ich auf void Ptr. D.h. Tabelle wird gefüttert Tab [0].Variable = &String Tab [0].Funktion = &FunktionString Tab [1].Variable = &IntZahl Tab [1].Funktion = &FunktionInt Abarbeiten des HTML Bereichs in einer Schleife mit 1. Aufruf der Tab [0].Funktion (Tab [0].Variable) 2. Aufruf der Tab [1].Funktion (Tab [1].Variable) Die Funktionen verarbeiten dann ebf. wieder die gleichen Typen (char, int, long, double) FunktionString (char *String) print string FunktionInt (int *IntZahl) print int Ich kann also die Funktion nicht direkt anspringen. Daher meine Frage nach dem richtigen Cast. Danke Daniel
Am Montag, 17. Oktober 2005 11:47 schrieb Daniel Bauer:
From: "Ralf Corsepius"
On Mon, 2005-10-17 at 10:04 +0200, Daniel Bauer wrote:
From: "Ralf Corsepius"
On Mon, 2005-10-17 at 08:43 +0200, Daniel Bauer wrote:
leider weiß ich nicht wie ich das hier am besten caste, hat jemand nen Tip, oder ne Quelle zum nachlesen?
man 3 printf
void ausgabe (char *Var, void *Val) { fprintf (stdout, ">%s<\n>%s<\n", Var, Val); }
Worin besteht dein Problem?
Du willst einen "void*" nach stdout ausgeben? Einen void* als %s auszugeben macht keinen Sinn. %s ist nur für char* definiert.
Die entscheidende Frage wäre: Als was willst Du den "void*" ausgeben?
Ich nehme mal an, Du suchst %p.
nein, es ist so richtig wie's dasteht,
Dem ist nicht so. Dein Code ist fehlerhaft, falsch und, schlimmer noch ein Sicherheitsrisiko.
mein Problem ist, daß ich mir variablen Funktionen und Parametern arbeite.
Keine Ahnung was Du unter variablen Funktionen und variablen Parametern verstehst, Funktionen mit variablen Argumentlisten werden heutzutage üblicherweise mittels
verarbeitet. Sie mittels void* zu ersetzen zu wollen ist schlichtweg unsauber.
Ich habe einen "Würgaround" geschafft, indem ich das ganze wie unten gelöst habe, hatte aber die Hoffnung auf diesen Umweg durch richtiges casten verzichten zu können.
void ausgabe (char *Var, void *Val) { char *Str; Str = Val; fprintf (stdout, ">%s<\n>%s<\n", Var, Str); }
Ein übler Hack - Ich kann nur davon abraten, weil es keinen Zusammenhang zwischen \0-terminierten c-Strings (Nur solche kann printf verarbeiten) und void* gibt.
Wenn deine "void*" \0-terminierte c-Strings sind, solltest Du sie auch als solche an diese Funktion übergeben. Und wenn schon casten (Wovon ich mit Nachdruck abrate), dann besser unmittelbar im Funktionsaufruf.
Noch weiterausgeholt, generell sollten sich derartige Casts immer vermeiden lassen. Erscheinen sie als unvermeidbar, deutet das auf ein Problem in deinem Code hin (Falsch gewählter Typ).
Hallo Ralf,
ich finde Deine Aussage "das alles falsch ist" - ohne den kompletten Projektbereich zu kennen - etwas heftig.
Einfach gesagt: es geht darum das mein Programm sich eines Webservers bedient und dessen Ein- und Ausgaben steuert/empfängt. Zum Aufbau des HTML Codes benutze ich eine Funktionstabelle die mit div. Parametern gefüttert und zur Ausgabezeit angesprochen wird. Da in dieser Funktion alle Arten (char, int, long, double) verarbeitet werden, setze ich auf void Ptr.
D.h. Tabelle wird gefüttert Tab [0].Variable = &String Tab [0].Funktion = &FunktionString
Tab [1].Variable = &IntZahl Tab [1].Funktion = &FunktionInt
Abarbeiten des HTML Bereichs in einer Schleife mit 1. Aufruf der Tab [0].Funktion (Tab [0].Variable) 2. Aufruf der Tab [1].Funktion (Tab [1].Variable)
Die Funktionen verarbeiten dann ebf. wieder die gleichen Typen (char, int, long, double) FunktionString (char *String) print string
FunktionInt (int *IntZahl) print int
Ich kann also die Funktion nicht direkt anspringen. Daher meine Frage nach dem richtigen Cast.
Danke Daniel
Hallo Meine erste Frage währe ob du unbedingt in C codieren musst, ansonsten würden sich ja eine C++ Templatefunktion anbieten: template<class T> void ausgabe(char* str, T i) { std::cout << str << i << std::endl; } Hier musst du dann lediglich darauf achten, das du nur Typen übergibst, die man auch mit dem << Operator ausgeben kann. Also wenn du auf diese weise selbsterstellte Klassen ausgeben willst musst du den Operator überladen, ansonsten gibt es nen Compilerfehler. Wäre meiner Meinung nach so die sauberste Lösung. Gruß Andre
From: "Andre Rudlaff"
Am Montag, 17. Oktober 2005 11:47 schrieb Daniel Bauer:
From: "Ralf Corsepius"
On Mon, 2005-10-17 at 10:04 +0200, Daniel Bauer wrote:
From: "Ralf Corsepius"
On Mon, 2005-10-17 at 08:43 +0200, Daniel Bauer wrote:
leider weiß ich nicht wie ich das hier am besten caste, hat jemand nen Tip, oder ne Quelle zum nachlesen?
man 3 printf
void ausgabe (char *Var, void *Val) { fprintf (stdout, ">%s<\n>%s<\n", Var, Val); }
Worin besteht dein Problem?
Du willst einen "void*" nach stdout ausgeben? Einen void* als %s auszugeben macht keinen Sinn. %s ist nur für char* definiert.
Die entscheidende Frage wäre: Als was willst Du den "void*" ausgeben?
Ich nehme mal an, Du suchst %p.
nein, es ist so richtig wie's dasteht,
Dem ist nicht so. Dein Code ist fehlerhaft, falsch und, schlimmer noch ein Sicherheitsrisiko.
mein Problem ist, daß ich mir variablen Funktionen und Parametern arbeite.
Keine Ahnung was Du unter variablen Funktionen und variablen Parametern verstehst, Funktionen mit variablen Argumentlisten werden heutzutage üblicherweise mittels
verarbeitet. Sie mittels void* zu ersetzen zu wollen ist schlichtweg unsauber.
Ich habe einen "Würgaround" geschafft, indem ich das ganze wie unten gelöst habe, hatte aber die Hoffnung auf diesen Umweg durch richtiges casten verzichten zu können.
void ausgabe (char *Var, void *Val) { char *Str; Str = Val; fprintf (stdout, ">%s<\n>%s<\n", Var, Str); }
Ein übler Hack - Ich kann nur davon abraten, weil es keinen Zusammenhang zwischen \0-terminierten c-Strings (Nur solche kann printf verarbeiten) und void* gibt.
Wenn deine "void*" \0-terminierte c-Strings sind, solltest Du sie auch als solche an diese Funktion übergeben. Und wenn schon casten (Wovon ich mit Nachdruck abrate), dann besser unmittelbar im Funktionsaufruf.
Noch weiterausgeholt, generell sollten sich derartige Casts immer vermeiden lassen. Erscheinen sie als unvermeidbar, deutet das auf ein Problem in deinem Code hin (Falsch gewählter Typ).
Hallo Ralf,
ich finde Deine Aussage "das alles falsch ist" - ohne den kompletten Projektbereich zu kennen - etwas heftig.
Einfach gesagt: es geht darum das mein Programm sich eines Webservers bedient und dessen Ein- und Ausgaben steuert/empfängt. Zum Aufbau des HTML Codes benutze ich eine Funktionstabelle die mit div. Parametern gefüttert und zur Ausgabezeit angesprochen wird. Da in dieser Funktion alle Arten (char, int, long, double) verarbeitet werden, setze ich auf void Ptr.
D.h. Tabelle wird gefüttert Tab [0].Variable = &String Tab [0].Funktion = &FunktionString
Tab [1].Variable = &IntZahl Tab [1].Funktion = &FunktionInt
Abarbeiten des HTML Bereichs in einer Schleife mit 1. Aufruf der Tab [0].Funktion (Tab [0].Variable) 2. Aufruf der Tab [1].Funktion (Tab [1].Variable)
Die Funktionen verarbeiten dann ebf. wieder die gleichen Typen (char, int, long, double) FunktionString (char *String) print string
FunktionInt (int *IntZahl) print int
Ich kann also die Funktion nicht direkt anspringen. Daher meine Frage nach dem richtigen Cast.
Danke Daniel
Hallo
Meine erste Frage währe ob du unbedingt in C codieren musst, ansonsten würden sich ja eine C++ Templatefunktion anbieten:
template<class T> void ausgabe(char* str, T i) { std::cout << str << i << std::endl; }
Hier musst du dann lediglich darauf achten, das du nur Typen übergibst, die man auch mit dem << Operator ausgeben kann. Also wenn du auf diese weise selbsterstellte Klassen ausgeben willst musst du den Operator überladen, ansonsten gibt es nen Compilerfehler. Wäre meiner Meinung nach so die sauberste Lösung.
Hallo Andre, nachdem ich das programieren noch vor C++ gelernt habe, konnte ich mich leider nie damit anfreunden - ich verstehe es einfach nicht - daher wollte ich natürlich auf C bleiben. Trotzdem nochmals vielen Dank Daniel
Am 17 Oct 2005 um 18:07 hat Daniel Bauer geschrieben:
Hallo Andre,
nachdem ich das programieren noch vor C++ gelernt habe, konnte ich mich leider nie damit anfreunden - ich verstehe es einfach nicht - daher wollte ich natürlich auf C bleiben.
Trotzdem nochmals vielen Dank Daniel
Hallo Daniel, das mit den << Operatoren finde ich auch die einfachste Lösung. Bezogen auf C ist das aber in vergleichbarer Weise machbar. Definiere für jeden Deiner Typen eine solche Funktion. Wenn Du dann einen char* als zweiten Parameter übergibst, wird auch die Funktion mit dem char* verwendet. Wenn es z.B. int ist, wird die mit dem int verwendet. Wenn Du unbedingt einen void* verwenden willst, wie willst Du denn den übergebenen Typ herausfinden ? Wenn Du zu einem char* castest, aber einen int* übergibst, kommt schlicht weg Mist raus. Und das ist nur der beste Fall. Übrigens, ich bin schnell zu C++ gewechselt, als ich erkannt hatte, wie einfach der Quelltext hinterher lesbar ist. (Ich meine bezogen auf das Problem, nicht auf die Sprache C++ selbst) Lothar -- Lothar Behrens | Rapid Prototyping ... Rosmarinstr 3 | 40235 Düsseldorf | www.lollisoft.de
Am Montag, 17. Oktober 2005 11:47 schrieb Daniel Bauer:
Hallo Ralf,
ich finde Deine Aussage "das alles falsch ist" - ohne den kompletten Projektbereich zu kennen - etwas heftig.
finde ich auch, aber etwas mehr info vorneweg wäre ganz hilfreich gewesen, aber da ist sie ja:
Einfach gesagt: es geht darum das mein Programm sich eines Webservers bedient und dessen Ein- und Ausgaben steuert/empfängt. Zum Aufbau des HTML Codes benutze ich eine Funktionstabelle die mit div. Parametern gefüttert und zur Ausgabezeit angesprochen wird. Da in dieser Funktion alle Arten (char, int, long, double) verarbeitet werden, setze ich auf void Ptr.
D.h. Tabelle wird gefüttert Tab [0].Variable = &String Tab [0].Funktion = &FunktionString
Tab [1].Variable = &IntZahl Tab [1].Funktion = &FunktionInt
Abarbeiten des HTML Bereichs in einer Schleife mit 1. Aufruf der Tab [0].Funktion (Tab [0].Variable) 2. Aufruf der Tab [1].Funktion (Tab [1].Variable)
Die Funktionen verarbeiten dann ebf. wieder die gleichen Typen (char, int, long, double) FunktionString (char *String) print string
FunktionInt (int *IntZahl) print int
Ich kann also die Funktion nicht direkt anspringen. Daher meine Frage nach dem richtigen Cast.
Mit einem allmächtigen cast kann ich leider auch nicht dienen, du wirst wohl auch noch Informationen zum richtigen Typ in der Tabelle ablegen müssen ( Tab[0].typ ), um dann in einem switch-Statement den richtigen cast zu benutzen. Nun das ganze in einer Funktion verstecken, die einen Tabelleneintrag übernimmt und die Funktion für Dich aufruft: void funCall(tabEntry *entry) { switch(entry->typ){ case /* konstante enum o.ä. für int */: (/*richtiger FP-Typ*/)(entry->Funktion)((int)(entry->Variable)); case /* ... */: default: /* Fehlerbehandlung */ } } oder so, wenn die Tabelle global verfügbar ist (due Struktur der Applikation lässt darauf schliessen...) kannst Du einfach nur den index übergeben... Damit kannst Du schon recht flexibel arbeiten. Und da Du den Typ schon beim Anlegen der Tabelle kennst (anders gehts AFAIK kaum), ist das ganze auch weniger riskant was Pufferüberläufe angeht... Nachteil: wenn Du neue Typen (structs etc) einführst musst Du die Funktion funCall und die Stelle, an der die Tabelle gefüllt wird, ändern (aber auch nicht mehr)...
Danke Daniel
HTH, Manfred Gahr P.S.: Nur um einer endlosen Diskussion vorzubeugen: Natürlich kann man das in C++ mit Templates oder Vererbung schöner schreiben, aber hier war explizit C gefragt...
On Tue, 2005-10-18 at 20:52 +0200, Manfred Gahr wrote:
Am Montag, 17. Oktober 2005 11:47 schrieb Daniel Bauer:
Hallo Ralf,
ich finde Deine Aussage "das alles falsch ist" - ohne den kompletten Projektbereich zu kennen - etwas heftig.
finde ich auch, aber etwas mehr info vorneweg wäre ganz hilfreich gewesen, aber da ist sie ja:
Dann halt noch ein letztes Mal: Einen void* über %s in printf auszugeben ist immer falsch - Ob Euch das gefällt oder nicht. Daran ändert auch der Hintergrund einer Applikation nichts.
Nur um einer endlosen Diskussion vorzubeugen: Natürlich kann man das in C++ mit Templates oder Vererbung schöner schreiben, ... Grober Irrtum ... Ob C oder C++ ändert nichts an der Problematik. Das Problem sieht in C++ nur anders aus.
Ralf
From: "Manfred Gahr"
Am Montag, 17. Oktober 2005 11:47 schrieb Daniel Bauer:
Einfach gesagt: es geht darum das mein Programm sich eines Webservers bedient und dessen Ein- und Ausgaben steuert/empfängt. Zum Aufbau des HTML Codes benutze ich eine Funktionstabelle die mit div. Parametern gefüttert und zur Ausgabezeit angesprochen wird. Da in dieser Funktion alle Arten (char, int, long, double) verarbeitet werden, setze ich auf void Ptr.
D.h. Tabelle wird gefüttert Tab [0].Variable = &String Tab [0].Funktion = &FunktionString
Tab [1].Variable = &IntZahl Tab [1].Funktion = &FunktionInt
Abarbeiten des HTML Bereichs in einer Schleife mit 1. Aufruf der Tab [0].Funktion (Tab [0].Variable) 2. Aufruf der Tab [1].Funktion (Tab [1].Variable)
Die Funktionen verarbeiten dann ebf. wieder die gleichen Typen (char, int, long, double) FunktionString (char *String) print string
FunktionInt (int *IntZahl) print int
Ich kann also die Funktion nicht direkt anspringen. Daher meine Frage nach dem richtigen Cast.
Mit einem allmächtigen cast kann ich leider auch nicht dienen, du wirst wohl auch noch Informationen zum richtigen Typ in der Tabelle ablegen müssen ( Tab[0].typ ), um dann in einem switch-Statement den richtigen cast zu benutzen. Nun das ganze in einer Funktion verstecken, die einen Tabelleneintrag übernimmt und die Funktion für Dich aufruft:
void funCall(tabEntry *entry) { switch(entry->typ){ case /* konstante enum o.ä. für int */: (/*richtiger FP-Typ*/)(entry->Funktion)((int)(entry->Variable)); case /* ... */: default: /* Fehlerbehandlung */ } }
oder so, wenn die Tabelle global verfügbar ist (due Struktur der Applikation lässt darauf schliessen...) kannst Du einfach nur den index übergeben...
Damit kannst Du schon recht flexibel arbeiten. Und da Du den Typ schon beim Anlegen der Tabelle kennst (anders gehts AFAIK kaum), ist das ganze auch weniger riskant was Pufferüberläufe angeht... Nachteil: wenn Du neue Typen (structs etc) einführst musst Du die Funktion funCall und die Stelle, an der die Tabelle gefüllt wird, ändern (aber auch nicht mehr)... Hallo Manfred,
danke für die Info, ich werde mir das genauer ansehen, ob ich das als Lösung verwenden kann, od. ob ich bei meinem "Schmutztrick" bleibe. Danke Daniel
participants (5)
-
Andre Rudlaff
-
Daniel Bauer
-
lothar.behrens@lollisoft.de
-
Manfred Gahr
-
Ralf Corsepius