Welche Größe hat ein Zeiger auf eine Klasse?
-
Hi,
ich habe hier einen Code bei dem mein Compiler an ein paar Stellen ein paar Warnungen ausgibt (VC 2003). Die Warnungen treten immer im Bezug mit der Referenzierung auf eine Klasse auf. z.B.c:\foo\foo.cpp(xx) : warning C4312: 'Typumwandlung': Konvertierung von 'LONG' in größeren Typ 'myClass *'
als Ergbenis z.B. von folgendem Aufruf:
myClass *pThis; pThis = (myClass*) GetWindowLongPtr( hWnd, GWLP_USERDATA );GetWindowLongPtr gibt als Rückgabetyp LONG zurück. Ich verstehe dass mich der Compiler warnen möchte, dass pThis größer ist als LONG, was unter Window 32 bit int unsigned ist. Allerdings verstehe ich nicht, warum die Referenz auf die Klasse größer sein soll als 32Bit. Ich habe einen waschechten 32-Bit Prozessor, mit einem 32-Bit Compiler, warum sollten hier Adressen größer als 32 Bit aufgelöst werden, wenn es theoretisch maximal 4GB RAM geben kann (ich weiss. Sind in wirklichkeit weniger).
Irgendjemand der mit weiterhelfen kann?mfg Sven
P.S. Alter C Programmierer der seine ersten Erfahrungen in C++ sammelt
-
Ein Zeiger ist IMMER (auf einem 32Bit-Rechner) 4 Bytes groß.
-
Hm und warum warnt mich dann VC++ 2003 vor dem Datenverlust bei der Konvertierung?
-
sgergen schrieb:
Hm und warum warnt mich dann VC++ 2003 vor dem Datenverlust bei der Konvertierung?
Hmm, gute Frage...hast du mal probiert den (long)Return-Wert in void* zu casten...was sagt er dann (oder in*)
PS: nur dann NICHT verwenden...geht nur um die Warnung!
-
Stell mal die 64-Bit Warnungen ab. Kommt die Meldung dann immer noch?
-
Thx. Der Compilerschalter /Wp64 wars.
Das ganze wirft allerdings unweigerlich eine neue Frage in mir auf. Die 64 Bit Rechner drüften auch in Homebereich irgendwann zum Standard werden. Seine Programme dann auf das neue System zu portieren dürfte eine Menge Arbeit verursachen wenn man nicht von vornerein ein paar Sachen berücksichtigt hat. Ist es möglich schon jetzt C++ Programme zu schreiben die sich später 1:1 auf einem 64Bit Rechner übersetzten lassen würden? Das ganze könnte meiner Meinung nach nur funktionieren wenn man sich komplett auf ein Framework wie die MFC stützt. Sobald intensiver Gebrauch des W32 SDK ist müsste es ernsthafte Probleme geben. Gibt es irgendwelche Seiten im Netz die sich um diese Problematik kümmern?Sven
-
in deinem fall ist das nur ne falschmeldung. du benutzt ja schon die funktion die auf 64-bit vorbereitet ist.
-
CodeFinder schrieb:
Ein Zeiger ist IMMER (auf einem 32Bit-Rechner) 4 Bytes groß.
Nicht alle...
-
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/win64/win64/getting_ready_for_64_bit_windows.asp
http://cache-www.intel.com/cd/00/00/01/79/17969_codeclean_r02.pdf
-
In C++ gibts auch Zeiger die größer sind als 4Byte, nen tollter Artikel dazu: http://www.codeproject.com/cpp/FastDelegate.asp
-
Dein Problem liegt vermutlich an deinem Platform SDK, denn GetWindowLongPtr gibt nicht LONG, sondern LONG_PTR zurück. Dann gibt's auch keine Warnungen. Habe hier selbst ein Platform SDK von 2005, und da wird LONG_PTR nur bei _WIN64 zurückgegeben. Was aber eigentlich immer so sein sollte, egal ob _WIN32 oder _WIN64. Ich würde die 64 Bit Kompatibilitätsüberwachung auf jeden Fall eingeschaltet lassen und den Rückgabewert erst nach LONG_PTR casten.
pThis = (myClass*) (LONG_PTR) GetWindowLongPtr( hWnd, GWLP_USERDATA );Sieht zwar etwas seltsam aus, sollte aber problemlos laufen. Wobei ich als C++ Programmierer natürlich andere Casts verwenden würde.

-
Dann hab ich nochmal ne Frage:
Aber Zeiger sind doch auf 64Bit Systemen größer (bzog. auf den Speicherverbrauch) als
auf 32Bit Systemen, oder ?...Wieviel ?
-
CodeFinder schrieb:
Dann hab ich nochmal ne Frage:
Aber Zeiger sind doch auf 64Bit Systemen größer (bzog. auf den Speicherverbrauch) als
auf 32Bit Systemen, oder ?...Wieviel ?
LONG_PTR ist ja auch nicht immer gleich groß, sondern groß genug den Zeiger zu speichern.
-
CodeFinder schrieb:
Dann hab ich nochmal ne Frage:
Aber Zeiger sind doch auf 64Bit Systemen größer (bzog. auf den Speicherverbrauch) als
auf 32Bit Systemen, oder ?...Wieviel ?
Datenzeiger sind auf gängigen 64-bit Systemen doppelt so groß wie auf gängigen 32-bit Systemen, nämlich 8-Byte.
-
Hm ok danke erstmal...
HumeSikkins schrieb:
CodeFinder schrieb:
Dann hab ich nochmal ne Frage:
Aber Zeiger sind doch auf 64Bit Systemen größer (bzog. auf den Speicherverbrauch) als
auf 32Bit Systemen, oder ?...Wieviel ?
Datenzeiger sind auf gängigen 64-bit Systemen doppelt so groß wie auf gängigen 32-bit Systemen, nämlich 8-Byte.
Hm...daraus kann man doch dann schließen
, das auf einem 32bit System, Zeiger 4 Byte verbrauchen...
Warum stimmt das:CodeFinder schrieb:
Ein Zeiger ist IMMER (auf einem 32Bit-Rechner) 4 Bytes groß.
dann nicht ?
Danke schon mal für die Aufklärung

-
@groovemaster:
Der Code lässt sich in der Tat problemlos ohne Warnungen kompilieren. Und hierbei sehe ich auch keinerlei Probleme beim Umstieg auf 64 Bit. Was mich eher zum grübeln bringt ist:SetWindowLongPtr(hWnd,GWLP_USERDATA,(LONG)pThis);Caste ich hier impliziet
(LONG)(LONG_PTR)pThiswürde ich hier bei der 64Bit Version Probleme bekommen. da ich den LONG_PTR in einen LONG kovertiert habe, was auch nach der neuen SDK immer noch 32Bit sein müssten. Bei
(LONG_PTR)pThiswäre das Statement zwar korrekt, allerdings kann ich es nicht ohne Warunungen mit meinem 32Bit Compiler ausführen.
Sven
-
CodeFinder schrieb:
Hm ok danke erstmal...
HumeSikkins schrieb:
CodeFinder schrieb:
Dann hab ich nochmal ne Frage:
Aber Zeiger sind doch auf 64Bit Systemen größer (bzog. auf den Speicherverbrauch) als
auf 32Bit Systemen, oder ?...Wieviel ?
Datenzeiger sind auf gängigen 64-bit Systemen doppelt so groß wie auf gängigen 32-bit Systemen, nämlich 8-Byte.
Hm...daraus kann man doch dann schließen
, das auf einem 32bit System, Zeiger 4 Byte verbrauchen...
Warum stimmt das:CodeFinder schrieb:
Ein Zeiger ist IMMER (auf einem 32Bit-Rechner) 4 Bytes groß.
dann nicht ?
Es gibt einen Unterschied zwischen Datenzeigern und Funktionszeigern. Datenzeiger (Zeiger auf einen Typen wie int, char, FooBar) sind auf gängigen 32-bit Systemen *immer* 4-Byte groß und Konvertierungen zwischen dem Standard-Integer (int bzw. long) und einem solchen Zeiger sind hier gefahrlos möglich.
Für Funktionszeiger (dazu gehören insbesondere auch Memberfunktionszeiger) hingegen muss das nicht gelten. Normale Funktionszeiger sind in der Regel zwar auch nur Adressen (und damit äquivalent zu Datenzeigern), der Standard schreibt dies aber nicht vor. Spätestens bei Memberfunktionszeigern wird es allerdings komplizierter, da hier zusätzliche Informationen gespeichert werden müssen (z.B. wenn virtuelle Funktionen ins Spiel kommen).
Btw: Die Grütze die der VC 6.0 bei Memberfunktionszeigern macht (siehe dazu den von Dr. Prof verlinkten Artikel) ist allerdings nicht Standard-Konform.
-
LOL, ok dann danke ich dir mal für deine Ausführungen

-
sgergen schrieb:
Was mich eher zum grübeln bringt ist:
SetWindowLongPtr(hWnd,GWLP_USERDATA,(LONG)pThis);Caste ich hier impliziet
(LONG)(LONG_PTR)pThiswürde ich hier bei der 64Bit Version Probleme bekommen. da ich den LONG_PTR in einen LONG kovertiert habe, was auch nach der neuen SDK immer noch 32Bit sein müssten.
Hmmm...habe jetzt noch mal in meinem 2005er SDK nachgeschaut, und da ist GetWindowLongPtr/SetWindowLongPtr tatsächlich nur ein define auf GetWindowLong/SetWindowLong. Das ist meiner Meinung nach ein Bug, da dadurch die Signatur verfälscht wird. Mich würde mal interessieren, was Jochen dazu meint. Wie auch immer, erstmal könntest du versuchen, ein aktuelles Platform SDK zu installieren. Evtl. ist das dort behoben. Sollte das nicht helfen, hätte ich als zweite Möglichkeit noch Folgendes anzubieten:
#ifdef GetWindowLongPtr #undef GetWindowLongPtr LONG_PTR GetWindowLongPtr(HWND hWnd, int nIndex); #endif #ifdef SetWindowLongPtr #undef SetWindowLongPtr LONG_PTR SetWindowLongPtr(HWND hWnd, int nIndex, LONG_PTR dwNewLong); #endifDas schreibst du dann _nachdem_ <windows.h> eingebunden wurde, und _bevor_ du die Funktionen aufrufst.
Bin zwar kein Freund von solchen Hacks, momentan würden mir aber nur Lösungen einfallen, die mir noch unsympathischer wären.