Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
La conversione del codice da compilare per Microsoft Windows a 32 e 64 bit è semplice. È sufficiente seguire alcune semplici regole sul cast di puntatori e usare i nuovi tipi di dati nel codice. Di seguito sono riportate le regole per la manipolazione del puntatore.
Non eseguire il cast dei puntatori a int, long, ULONGo DWORD.
Se è necessario eseguire il cast di un puntatore per testare alcuni bit, impostare o cancellare bit oppure modificare il relativo contenuto, usare il tipo UINT_PTR o INT_PTR. Questi tipi sono tipi integrali che si adattano alle dimensioni di un puntatore per Windows a 32 e a 64 bit, ad esempio ULONG per Windows a 32 bit e _int64 per Windows a 64 bit. Si supponga, ad esempio, di convertire il codice seguente:
ImageBase = (PVOID)((ULONG)ImageBase | 1);Come parte del processo di conversione, è necessario modificare il codice nel modo seguente:
ImageBase = (PVOID)((ULONG_PTR)ImageBase | 1);Usare UINT_PTR e INT_PTR dove appropriato (e se si è incerti se sono necessari, non c'è alcun danno nell'usarli solo nel caso). Non eseguire il cast dei puntatori ai tipi ULONG, LONG, INT, UINTo DWORD.
Si noti che HANDLE è definito come void*, pertanto il typecasting di un valore HANDLE a un valore ULONG per testare, impostare o cancellare i bit con ordine minimo 2 è un errore in Windows a 64 bit.
Utilizzare la funzione PtrToLong o PtrToUlong per troncare i puntatori.
Se è necessario troncare un puntatore a un valore a 32 bit, usare la funzione PtrToLong o PtrToUlong (definita in Basetsd.h). Queste funzioni disabilitano l'avviso di troncamento del puntatore per la durata della chiamata.
Usare queste funzioni con attenzione. Dopo aver convertito una variabile puntatore usando una di queste funzioni, non usarla mai di nuovo come puntatore. Queste funzioni troncano i 32 bit superiori di un indirizzo, che in genere sono necessari per accedere alla memoria a cui originariamente fa riferimento il puntatore. L'uso di queste funzioni senza un'attenta considerazione comporterà la fragilità del codice.
Prestare attenzione quando si usano valori POINTER_32 nel codice, il quale può essere compilato come codice a 64 bit. Il compilatore estenderà il puntatore quando viene assegnato a un puntatore nativo nel codice a 64 bit, non estenderà il puntatore con zeri.
Prestare attenzione quando si usano i valori POINTER_64 nel codice che può essere compilato come codice a 32 bit. Il compilatore firmerà l'estensione del puntatore nel codice a 32 bit, senza estendere il puntatore.
Prestare attenzione all'uso dei parametri OUT.
Si supponga, ad esempio, di avere una funzione definita come segue:
void func( OUT PULONG *PointerToUlong );Non chiamare questa funzione come indicato di seguito.
ULONG ul; PULONG lp; func((PULONG *)&ul); lp = (PULONG)ul;Usare invece la chiamata seguente.
PULONG lp; func(&lp);La conversione di tipo &ul in PULONG* impedisce un errore del compilatore, ma la funzione inserirà un valore di puntatore di 64 bit nella memoria in &ul. Questo codice funziona in Windows a 32 bit, ma causerà il danneggiamento dei dati in Windows a 64 bit e sarà sottile e difficile da individuare. In sintesi: non fare giochetti con il codice C—chiaro e semplice è meglio.
Prestare attenzione alle interfacce polimorfiche.
Non creare funzioni che accettano parametri DWORD per i dati polimorfici. Se i dati possono essere un puntatore o un valore integrale, usare il tipo UINT_PTR o PVOID.
Ad esempio, non creare una funzione che accetta una matrice di parametri di eccezione tipizzati come valori DWORD. La matrice deve essere una matrice di valori DWORD_PTR. Pertanto, gli elementi della matrice possono contenere indirizzi o valori integrali a 32 bit. La regola generale è che se il tipo originale è DWORD e deve essere di larghezza puntatore, convertirlo in un valore DWORD_PTR. Ecco perché esistono tipi di precisione puntatore corrispondenti. Se si dispone di codice che usa DWORD, ULONGo altri tipi a 32 bit in modo polimorfico (ovvero si vuole che il parametro o il membro della struttura contenga un indirizzo), usare UINT_PTR al posto del tipo corrente.
Usare le nuove funzioni della classe finestra.
Se sono presenti dati privati della finestra o della classe che contengono puntatori, il codice dovrà usare le nuove funzioni seguenti:
Queste funzioni possono essere usate sia in Windows a 32 che a 64 bit, ma sono necessarie in Windows a 64 bit. Prepararsi per la transizione usando queste funzioni ora.
Inoltre, è necessario accedere a puntatori o handle nei dati privati della classe usando le nuove funzioni in Windows a 64 bit. Per facilitare l'individuazione di questi casi, gli indici seguenti non sono definiti in Winuser.h durante una compilazione a 64 bit:
- GWL_WNDPROC
- GWL_HINSTANCE
- GWL_HWNDPARENT
- GWL_USERDATA
Winuser.h definisce invece i nuovi indici seguenti:
- GWLP_WNDPROC
- GWLP_HINSTANCE
- GWLP_HWNDPARENT
- GWLP_USERDATA
- GWLP_ID
Ad esempio, il codice seguente non viene compilato:
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)MyWndProc);Deve essere modificato nel modo seguente:
SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MyWndProc);Quando si imposta il membro cbWndExtra della struttura WNDCLASS , assicurarsi di riservare spazio sufficiente per i puntatori. Ad esempio, se attualmente si stanno riservando byte di sizeof(DWORD) per un valore del puntatore, si riservino byte di sizeof(DWORD_PTR).
Accedere a tutti i dati della finestra e della classe usando FIELD_OFFSET.
È comune accedere ai dati delle finestre usando offset codificati staticamente. Questa tecnica non è portabile a Windows a 64 bit. Per rendere portabile il codice, accedere ai dati della finestra e della classe usando la macro FIELD_OFFSET. Non presupporre che il secondo puntatore abbia un offset pari a 4.
Il LPARAM, WPARAMe tipi LRESULT cambiano dimensione con la piattaforma.
Durante la compilazione di codice a 64 bit, questi tipi si espandono a 64 bit, perché in genere contengono puntatori o tipi integrali. Non combinare questi valori con DWORD, ULONG, UINT, INT, into valori long. Esaminare come usare questi tipi e assicurarsi di non troncare inavvertitamente i valori.