Adresse, Datentyp und Name einer Variablen zur Laufzeit bestimmen
-
Kóyaánasqatsi schrieb:
Und wenn man schonmal weiss, das eine ASCII-Kette besteht, dann kann man wohl eher sagen, dass es sich dabei um einen char handelt.
int value = 0x09204913; IsChar(&value, sizeof(value));
Heuristik will gelernt sein.
Dein Code verhält sich außerdem undefiniert, funktioniert also auf mehreren Ebenen nicht.
-
Kóyaánasqatsi schrieb:
Außerdem geht mir dein Verhalten auf die Nüsse...
Das mag zwar sein udn ruht vermutlich auf Gegenseitigkeit. Trotzdem solltet ihr sowas privat klären und nicht hier im Forum.
-
@pumuckl
Ok.Jau, den Code habe ich heute morgen schnell dahin geschmiert um zu hustbaer zu zeigen, was ich meine. So oder so wird es nahezu unmöglich, den genauen Datentypen zu ermitteln. Es sei denn, du legst sowas vorm kompilieren fest, dass würde mich dann auch interessieren
.
-
Kóyaánasqatsi schrieb:
Es sei denn, du legst sowas vorm kompilieren fest, dass würde mich dann auch interessieren
.
Steht zum Beispiel in meinem oberen Post.
Aber wie gesagt, besonders schön und sinnvoll ist das nicht.
-
danke erstmal für eure Antworten. Natürlich kann man die Adresse mittels dem Referenzoperator herausbekommen. Was passiert allerdings wenn ich damit Speicher allokiere, wo finde ich dann die Startadresse des zu belegenden Signalvektors? Mit &pSV1 &pSV2 usw. erhalte ich Adressen 1241464 1241468 im Abstand von 4 Bits / Bytes? Das sind ja nur die Adressen der Pointer, ich such allerdings den Anfang des zu belegenden Speichers den ich wie folgt allokiere...
pSV1 = (short int*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * sizeof(short int) * GlPar.nNperB);
Die Datentypen sind im voraus bekannt! Ich lege sie ja in einer Header-Datei an:
short int* pSV1;
int* pSV2;
long int* pSV3;
float* pSV4;
double* pSV5;Der Vorschlag von Nexus gefällt mir somit mal ganz gut. Das Stichwort heisst denke ich Funktion-Templates. Darüber lässt sich zumindest mit dem korrekten Datentyp arbeiten.
Ich will mich jetzt mal, in Bezug auf den Namen der Variablen zur Laufzeit, vorsichtig äussern: ein Freund meinte das er im "Linker-Output (Map)" zu finden sein könnte. Kennt sich vielleicht damit jemand aus und weiß wie man da ran kommt?
-
cappasa schrieb:
danke erstmal für eure Antworten. Natürlich kann man die Adresse mittels dem Referenzoperator herausbekommen. Was passiert allerdings wenn ich damit Speicher allokiere, wo finde ich dann die Startadresse des zu belegenden Signalvektors? Mit &pSV1 &pSV2 usw. erhalte ich Adressen 1241464 1241468 im Abstand von 4 Bits / Bytes? Das sind ja nur die Adressen der Pointer, ich such allerdings den Anfang des zu belegenden Speichers den ich wie folgt allokiere...
pSV1 = (short int*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * sizeof(short int) * GlPar.nNperB);
Hm. Blöde Frage, aber ist dir bewusst, was Pointer sind? pSV1 ist ein Pointer, der Wert des Pointers ist eine Speicheradresse. HeapAlloc dürfte die Adresse des allokierten Speichers zurückgeben, (sonst könntest du ihn ja nie wiederfinden und benutzen), und die Zuweisung speichert diese Adresse in pSV1. Und deine Frage war jetzt, welche Anfangsadresse der Speicher hat, den du allokiert hast?
-
cappasa schrieb:
Ich will mich jetzt mal, in Bezug auf den Namen der Variablen zur Laufzeit, vorsichtig äussern: ein Freund meinte das er im "Linker-Output (Map)" zu finden sein könnte. Kennt sich vielleicht damit jemand aus und weiß wie man da ran kommt?
Das Problem ist, dass C++ keinen derartigen Mechanismus zur Verfügung stellt. Wenn du meinst dass dein Compiler das trotzdem kann, solltest du wenigstens mal erwähnen, um welchen Compiler es überhaupt geht.
Obwohl - die Art der Fragestellung, die gestellte Aufgabe und das Nicht-erwähnen des Compilers, das deutet alles eindeutig auf Visual C++ hin.
-
@troll
Ja ich benutze Visual Studio Professional 6 mein Programm läuft mit den MFC.@pumuckl
mir ist schon klar das ich damit die Adresse bekomme, allerdings wird ein größerer Speicherbereich reserviert. Ich würde jetzt nicht erwarten das der nächste reservierte Speicherbereich bei 1241468 beginnt wenn doch zuvor in 1241464 geschrieben wurde. Der Wert von pSV1 ist nach der Initialisierung genau derselbe wie zuvor beim Anlegen des Pointers! Und der geringe Abstand im Speicher zum nächsten macht mich ja gerade stutzig. 2 * 2Byte * 8192 das müsste einen wesentlich größeren Speicherplatz belegen...CString adr; adr.Format("%d", &pSV); m_List.InsertItem (0, adr);
vielleicht geht auch etwas bei der Konvertierung in einen String schief...
-
Ich bin jetzt nochmals mit dem Debugger durchgegangen und stelle fest, das nach der Initialisierung doch meine erwarteten Adressen kommen. Das Problem muss also in der Konvertierung liegen. Die Adressen sind ja hexadezimal, weiß vielleicht jemand wie ich sie passend als String, am besten so wie sie im Speicher stehen (0x0015e010), ausgeben kann?
MfG
cappasa
-
&pSV ergibt aber die Adresse von pSV und nicht die Adresse des Speicherbereichs. lass den Aressoperator weg und gib einfach den Wert von pSV aus, das ist die Adresse des Speichers den du allokiert hast.
-
ja danke nochmals, habs aber seit geraumer Zeit auch heraus gefunden, den Referenzoperator habe ich weggelassen und den Platzhalter mit %x für hexadezimale Ausgabe gesetzt.
Mit GetDataType übergebe ich nun die WAVEHDR Struktur und nType stellt die ausgewählte Zeile meiner Liste dar. So caste ich den aktuellen Datenpuffer auf den entsprechenden Datentyp.
Zu Beginn lege ich alle 5 Signalvektoren an und allokiere sie, sobald einer ausgewählt wurde, werden die übrigen 4 freigegeben und der gewählte Signalvektor wird mittels GetDataType in pDP.x1 (Linker Channel zum Zeichnen) geschrieben. ( pDP.x1 = GetDataType(lpwh, m_nSV); )void* CWiwoDlg::GetDataType(LPWAVEHDR lpwh, int nType) { switch(nType) { case 1: return (short int*)lpwh->lpData; case 2: return (int*)lpwh->lpData; case 3: return (long int*)lpwh->lpData; case 4: return (float*)lpwh->lpData; case 5: return (double*)lpwh->lpData; default: return (short int*)lpwh->lpData; } }
MfG Cappaja
-
Das Ganze in Kurz:
void* CWiwoDlg::GetDataType(LPWAVEHDR lpwh, int nType) { return lpwh->lpData; }
-
aber so übergebe ich pDP.x1 immer einen LONG Pointer. Ich will doch unterschiedliche Datentypen übergeben. Meine Liste befindet sich in einem extra Dialog auf welchen ich mit m_pSignal zugreife. Ich brauche ja die darin angelegten Signalvektoren sodass pDP.x1 diejenige Adresse besitzt, welche in der Liste ausgewählt wurde. Oder habe ich wo einen Denkfehler? Oder sollte ich auf den Rückgabetyp ganz verzichten und einfach die jeweilige Operation ausführen? also statt return gleich die Initialisierung in (pDP.x1 = m_pSignal->pSV1)
void* CWiwoDlg::GetDataType(LPWAVEHDR lpwh, int nType) { if(m_pSignal != NULL) { switch(nType) { case 1: m_pSignal->pSV1 = (short int*)lpwh->lpData; return m_pSignal->pSV1; case 2: m_pSignal->pSV2 = (int*)lpwh->lpData; return m_pSignal->pSV2; case 3: m_pSignal->pSV3 = (long int*)lpwh->lpData; return m_pSignal->pSV3; case 4: m_pSignal->pSV4 = (float*)lpwh->lpData; return m_pSignal->pSV4; case 5: m_pSignal->pSV5 = (double*)lpwh->lpData; return m_pSignal->pSV5; default: m_pSignal->pSV1 = (short int*)lpwh->lpData; return m_pSignal->pSV1; } } else return (short int*)lpwh->lpData; }
-
Ich blicke bei deinem Kram da nicht so recht durch, aber die Grundregel lautet: einem
void*
-Pointer kann man jeden anderen Pointer-Typ ohne Cast zuweisen. In die andere Richtung gehts natürlich nicht ohne Cast.
In C++ gibts übrigens mehrere Casting-Operatoren, z. B.static_cast
undreinterpret_cast
, mit jeweils eigener Semantik. Auf die weniger ausdrucksstarken C-Style Casts sollte man verzichten.