Considérations supplémentaires
Lors du portage de votre code, tenez compte des points suivants :
L’hypothèse suivante n’est plus valide :
#ifdef _WIN32 // Win32 code ... #else // Win16 code ... #endif
Toutefois, le compilateur 64 bits définit _WIN32 pour la compatibilité descendante.
L’hypothèse suivante n’est plus valide :
#ifdef _WIN16 // Win16 code ... #else // Win32 code ... #endif
Dans ce cas, la clause else peut représenter _WIN32 ou _WIN64.
Soyez prudent avec l’alignement du type de données. La macro TYPE_ALIGNMENT retourne les exigences d’alignement d’un type de données. Par exemple :
TYPE_ALIGNMENT( KFLOATING_SAVE )
== 4 sur x86, 8 sur le processeurTYPE_ALIGNMENT( UCHAR )
Intel Itanium == 1 partoutPar exemple, le code du noyau qui ressemble actuellement à ceci :
ProbeForRead( UserBuffer, UserBufferLength, sizeof(ULONG) );
doit probablement être remplacé par :
ProbeForRead( UserBuffer, UserBufferLength, TYPE_ALIGNMENT(IOCTL_STRUC) );
Les correctifs automatiques des exceptions d’alignement en mode noyau sont désactivés pour les systèmes Intel Itanium.
Soyez prudent avec les opérations NOT. Tenez compte des éléments suivants :
UINT_PTR a; ULONG b; a = a & ~(b - 1);
Le problème est que ~(b–1) produit « 0x0000 0000 xxxx xxxx » et non « 0xFFFF FFFF xxxx xxxx ». Le compilateur ne détecte pas cela. Pour résoudre ce problème, modifiez le code comme suit :
a = a & ~((UINT_PTR)b - 1);
Soyez prudent en effectuant des opérations non signées et signées. Tenez compte des éléments suivants :
LONG a; ULONG b; LONG c; a = -10; b = 2; c = a / b;
Le résultat est d’une ampleur inattendue. La règle est que si l’un des opérandes n’est pas signé, le résultat n’est pas signé. Dans l’exemple précédent, a est converti en valeur non signée, divisée par b, et le résultat est stocké dans c. La conversion n’implique aucune manipulation numérique.
Comme autre exemple, considérez les éléments suivants :
ULONG x; LONG y; LONG *pVar1; LONG *pVar2; pVar2 = pVar1 + y * (x - 1);
Le problème se produit parce que x n’est pas signé, ce qui rend l’expression entière non signée. Cela fonctionne bien, sauf si y est négatif. Dans ce cas, y est converti en valeur non signée, l’expression est évaluée à l’aide d’une précision 32 bits, mise à l’échelle et ajoutée à pVar1. Un nombre négatif non signé 32 bits devient un grand nombre positif de 64 bits, ce qui donne un résultat incorrect. Pour résoudre ce problème, déclarez x en tant que valeur signée ou saisissez-la explicitement en LONG dans l’expression.
Soyez prudent lorsque vous effectuez des allocations de taille fragmentaire. Par exemple :
struct xx { DWORD NumberOfPointers; PVOID Pointers[100]; };
Le code suivant est incorrect, car le compilateur va compléter la structure avec 4 octets supplémentaires pour effectuer l’alignement de 8 octets :
malloc(sizeof(DWORD) + 100*sizeof(PVOID));
Le code suivant est correct :
malloc(offsetof(struct xx, Pointers) + 100*sizeof(PVOID));
Ne passez pas à des
(HANDLE)0xFFFFFFFF
fonctions telles que CreateFileMapping. Utilisez plutôt INVALID_HANDLE_VALUE.Utilisez les spécificateurs de format appropriés lors de l’impression d’une chaîne. Utilisez %p pour imprimer des pointeurs en hexadécimal. Il s’agit du meilleur choix pour imprimer des pointeurs. Microsoft Visual C++ prend en charge %I pour imprimer des données polymorphes. Visual C++ prend également en charge %I64 pour imprimer des valeurs de 64 bits.