Pointermathematik/-symbolik
-
du willst praktisch sowas:
#include <iostream> using namespace std; class A { public: int a; int b; int c; }; typedef int A::*ptr; int main () { ptr c = &A::c; void *v = (void*)c; A a; a.a = 1; a.b = 2 a.c = 4; void *aptr = &a; int *vaptr = (int*)aptr; while ((char*)v) { ((char*)vaptr)++; --((char*)v); } cout << a.c << " = " << *vaptr << endl; }
kannst ja mal ausprobieren, ob das bei dir geht.
standardkonform ist das aber nicht mehr, da schon das casten von &A::c nach void* undefiniert ist (afair)
schau dir dein problem lieber noch mal an und überleg dir eine andere lösung
-
wieso machs du es so umständlich?
CA b; SB::test(b, ((char*)&b.sB) - ((char*)&b));
vielleicht solltes du dich mal mit templates bescheftigen
template<typename TofClass, typename TofMember> void test(TofClass & t, TofMember (TofClass::*p) ) { (t.*p)->VariableA = 1; } int main() { CA b; test( b, &b::sB ); }
-
offsetof
-
mir scheint, für die ganzen probleme, von nem kassenzeiger auf das member zu kommen, ist kein void* und kein offset nötig. das machen normale memberzeiger auch. irgendwie kann ich dem problem nicht folgen.
wenn du es mit gewallt wilst, hilft bestimmt sowas wie
int offset=(char*)&(((Klasse*)4711)->member)-(char*)(4711);
aber das ist ganz schrecklich.ich muß gestehen, daß ich sowas schon gemacht habe. aber es ist schrecklich. die lösungen, die wie typedef int A::*ptr; anfangen sind viel geiler, weil sie das typsystem von c++ nicht vergewaltigen und außerdem auch klappen, wenn du nen anderen compiler nimmst.
-
Okay also das mit Klassenzeiger->member hat mich schon mal richtig weiter gebracht.
---
Das andere Problem habt ihr auch gelöst. Jedoch nicht 100%ig so, wie ich es wollte.
(Aber trotzdem bis hierhin danke!!!)
Ihr habt den Ort einer Variable in der Klasse so bestimmt:CA b; int X= ((char*)&b.sB) - ((char*)&b);
Und eigentlich war das Problem noch komplizierter
denn zur Zeit des Funktionsaufrufs kennt man nur den Typ der Klasse, hat sie aber selbst noch nicht erstellt.
Ich habe aber dafür eine mögliche Lösung gefunden
(durch probieren und rumspielen nach einer Stunde)Ich erkläre das mal am Beispiel:
Man hat
class A { public: int b; int c; int d; };
und man will den Ort von d in A haben.
Das macht man so.int A::* H=&A::d; // Bei dieser Klasse ist H dann 8 (in Bytes)
Jetzt möchte ich das in eine int Variable kriegen aber ich weiß keinen guten Weg wie man es umwandeln soll. Eigentlich müsste es ja möglich sein, da man ja jeden Pointertyp in jeden anderen umwandeln kann, aber hier geht es nicht.
Ich habe dann das Problem mit der Konvertierung einfach umgangen, indem ich einen Pointer J gemacht habe der auf H zeigt und den man dann ja, im Gegensatz zu H, in jeden Pointer anderen umwandeln kann. In I wurde dann der Wert von J gespeichert.int A::* H=&A::d; int *J=(int*)&H; int I=*J; // I=8 (in Bytes)
Okay die letzten beiden Zeilen konnte ich zusammenfassen
int A::* H=&A::d; int I=*(int*)&H;
Aber bei den beiden übrigen Zeilen weiß ich nicht wie ich das machen soll. Ich möchte es aber gerne zu einer Zeile zusammenfassen, da ich es nur als Parameter benutzen werde.
Mir kommen insgesamt 3 Lösungsansätze in den Sinn wie man "A::*" in "int" in einer Zeile umwandeln könnte, die ich aber alle nicht hinkriege
Es gibt einen direkten Umwandlungsbefehl, den ich nicht kenne
2)
Die beiden Zeilen kann man durch einfache befehle wie ,&,(int) irgendwie zusammenbringen
3)
Die extra Funktiontemplate<typename V_Typ> V_Typ* make_Pointer(V_Typ v_Typ) { return &v_Typ; }
machen, so dass man schreiben kann
int I=*(int*)make_Pointer(&A::d);
Wobei ich dann irgendwie folgende Warnung wegbekommen müsste:
"Adresse einer lokalen Variablen oder eines temporaeren Wertes wird zurueckgegeben."Hey, oder gibt es so eine Funktion wie diese bereits als Standartbefehl?
---Falls jemand Lösungen zu einem der 3 Ansätze hat, bitte schreiben.
Danke im voraus[ Dieser Beitrag wurde am 01.05.2003 um 15:01 Uhr von Janko editiert. ]
-
struct foo { int a; int b; int c; }; int C = *(int*)&foo::c;
deine template funktion macht folgendes:
template <class T> T *bar (T t) { return &t; } //probier mal das ganze mit int: int *bar (int t) { return &t; //siehst du, was den compiler aufregt? i ist eine lokale kopie! } //und mit bar(&foo::c) passiert das: int foo::* * bar (int foo::*t) { return &t; }
du gibst also einen zeiger auf eine lokale kopie von einem int foo::* zeiger zurück. geht auch nicht gut.
bedenke: int foo::* ist bereits ein zeiger, und du willst ja keinen zeiger auf einen zeiger.im übrigen sind konvertierungen von zeigern auf elementvariablen zu irgendwelchen anderen typen außer zeiger auf elementvariablen der selben klasse nicht erlaubt:
struct foo { int i; double d; char c; }; int main () { int foo::*ip = &foo::i; ip = reinterpret_cast<int foo::*> (&foo::d); //ist erlaubt und genauso sinnvoll wie: int i, *ip2 = &i; double d; ip2 = reinterpret_cast<int*> (&d); int *i = reinterpret_cast<int*> (&foo::i); //ist NICHT erlaubt! und sollte //bei einem standardkonformen Compiler nicht funktionieren (gcc3.2 zb) //ein Grund, um auf C casts zu verzichten, den damit lässt sich ALLES konvertieren: int *i = (int*)&foo::i; }
also im prinzip passt du nicht mehr ganz in dieses forum
-
struct foo { int a; int b; int c; }; int C = *(int*)&foo::c;
Ich weiß jetzt nicht ganz warum du das hingeschrieben hast, bei mir funktioniert es nicht, bei dir etwa?
Ich erhalte folgenden Fehler:
error C2440: 'type cast' : 'int foo::*' kann nicht in 'int *' konvertiert werden
Es gibt keinen Kontext, in dem diese Konvertierung moeglich ist
**
Inzwischen habe ich aber die Lösung selbst gefunden.int C=(int)&((foo*)0)->c;
Das ist jetzt (endlich) die Stelle eines Members innerhalb der Klasse.
**
-----int *i = reinterpret_cast<int*> (&foo::i); //ist NICHT erlaubt! und sollte //bei einem standardkonformen Compiler nicht funktionieren (gcc3.2 zb) //ein Grund, um auf C casts zu verzichten, den damit lässt sich ALLES konvertieren: int *i = (int*)&foo::i;
Ist klar das es nicht erlaubt ist, hat ja bei mir auch nicht funktioniert.
Ich sehe aber bei deinen Kommentaren leider nicht ganz durch.
Was meinst du genau mit "C" casts und bezieht sich dein "den" (was sicherlich denn heißen sollte) auf C casts oder auf die Zeile code darunter?
Falls 2teres dann ist das schade, denn der Code funktioniert bei mir nicht. Ich erhalte wie oben folgenden Fehler:
error C2440: 'type cast' : 'int foo::*' kann nicht in 'int *' konvertiert werden
Es gibt keinen Kontext, in dem diese Konvertierung moeglich ist-----
im übrigen sind konvertierungen von zeigern auf elementvariablen zu irgendwelchen anderen typen außer zeiger auf elementvariablen der selben klasse nicht erlaubt:
[...]
also im Prinzip passt du nicht mehr ganz in dieses forumWarum nicht? Oder hatte mein Code vom letzten Post etwa bei dir nicht funktioniert? (Hierrauf bitte antworten)
class A { public: int b; int c; int d; }; int A::* H=&A::d; int I=*(int*)&H;
-
zum glück hat meinen fehler noch niemand entdeckt:
der C Cast ist hier sogar auch nicht erlaubt! fehler meinerseits (und von gcc)
wie gesagt, deshalb kann ich auch (int)&foo::c ohne fehlermeldung den compiler schlucken lassen!
-
wie gesagt, deshalb kann ich auch (int)&foo::c ohne fehlermeldung den
compiler schlucken lassen!Kannst du mir mal genau sagen wie du das gemacht hast? Bei mir funktioniert ja die Zeile nicht
-
ich gebe es einfach ein, keine warnung keine fehlermeldung.
mein Compiler ist gcc 3.2 bzw. mingw
-
Na toll meiner ist MSVC++ 6.0 und es gibt Fehler grrr.
Wie ist das bei den anderen?