Ulteriori considerazioni
Quando si effettua la conversione del codice, considerare i punti seguenti:
Il presupposto seguente non è più valido:
#ifdef _WIN32 // Win32 code ... #else // Win16 code ... #endif
Tuttavia, il compilatore a 64 bit definisce _WIN32 per la compatibilità con le versioni precedenti.
Il presupposto seguente non è più valido:
#ifdef _WIN16 // Win16 code ... #else // Win32 code ... #endif
In questo caso, la clausola else può rappresentare _WIN32 o _WIN64.
Prestare attenzione all'allineamento del tipo di dati. La macro TYPE_ALIGNMENT restituisce i requisiti di allineamento di un tipo di dati. Ad esempio:
TYPE_ALIGNMENT( KFLOATING_SAVE )
== 4 su x86, 8 su processoreTYPE_ALIGNMENT( UCHAR )
Intel Itanium == 1 ovunqueAd esempio, il codice kernel simile al seguente:
ProbeForRead( UserBuffer, UserBufferLength, sizeof(ULONG) );
probabilmente deve essere modificato in:
ProbeForRead( UserBuffer, UserBufferLength, TYPE_ALIGNMENT(IOCTL_STRUC) );
Le correzioni automatiche delle eccezioni di allineamento in modalità kernel sono disabilitate per i sistemi Intel Itanium.
Prestare attenzione alle operazioni NOT. Considerare quanto segue:
UINT_PTR a; ULONG b; a = a & ~(b - 1);
Il problema è che ~(b-1) produce "0x0000 0000 xxxx xxxx" e non "0xFFFF FFFF xxxx xxxx". Il compilatore non rileverà questa situazione. Per risolvere questo problema, modificare il codice nel modo seguente:
a = a & ~((UINT_PTR)b - 1);
Prestare attenzione a eseguire operazioni non firmate e firmate. Considerare quanto segue:
LONG a; ULONG b; LONG c; a = -10; b = 2; c = a / b;
Il risultato è inaspettatamente grande. La regola è che se uno degli operandi non è firmato, il risultato non è firmato. Nell'esempio precedente, un oggetto viene convertito in un valore senza segno, diviso per b e il risultato archiviato in c. La conversione non comporta alcuna manipolazione numerica.
Come altro esempio, considerare quanto segue:
ULONG x; LONG y; LONG *pVar1; LONG *pVar2; pVar2 = pVar1 + y * (x - 1);
Il problema si verifica perché x è senza segno, che rende l'intera espressione senza segno. Questo funziona bene, a meno che y non sia negativo. In questo caso, y viene convertito in un valore senza segno, l'espressione viene valutata usando precisione a 32 bit, ridimensionata e aggiunta a pVar1. Un numero negativo senza segno a 32 bit diventa un numero positivo a 64 bit di grandi dimensioni, che dà il risultato errato. Per risolvere questo problema, dichiarare x come valore firmato o digitarlo in modo esplicito su LONG nell'espressione.
Prestare attenzione quando si effettuano allocazioni di dimensioni a fasi. Ad esempio:
struct xx { DWORD NumberOfPointers; PVOID Pointers[100]; };
Il codice seguente non è corretto perché il compilatore riempirà la struttura con altri 4 byte per rendere l'allineamento a 8 byte:
malloc(sizeof(DWORD) + 100*sizeof(PVOID));
Il codice seguente è corretto:
malloc(offsetof(struct xx, Pointers) + 100*sizeof(PVOID));
Non passare
(HANDLE)0xFFFFFFFF
a funzioni come CreateFileMapping. Usare invece INVALID_HANDLE_VALUE.Utilizzare gli identificatori di formato appropriati durante la stampa di una stringa. Utilizzare %p per stampare i puntatori in formato esadecimale. Questa è la scelta migliore per i puntatori di stampa. Microsoft Visual C++ supporta %I per stampare dati polimorfici. Visual C++ supporta anche %I64 per stampare valori a 64 bit.