Дополнительные сведения
При переносе кода учитывайте следующие моменты.
Следующее предположение больше не является допустимым:
#ifdef _WIN32 // Win32 code ... #else // Win16 code ... #endif
Однако 64-разрядный компилятор определяет _WIN32 для обеспечения обратной совместимости.
Следующее предположение больше не является допустимым:
#ifdef _WIN16 // Win16 code ... #else // Win32 code ... #endif
В этом случае предложение else может представлять _WIN32 или _WIN64.
Будьте осторожны с выравниванием типов данных. Макрос TYPE_ALIGNMENT возвращает требования к выравниванию для типа данных. Например:
TYPE_ALIGNMENT( KFLOATING_SAVE )
== 4 в x86, 8 на процессореTYPE_ALIGNMENT( UCHAR )
Intel Itanium == 1 вездеНапример, код ядра, который в настоящее время выглядит следующим образом:
ProbeForRead( UserBuffer, UserBufferLength, sizeof(ULONG) );
Вероятно, следует изменить на:
ProbeForRead( UserBuffer, UserBufferLength, TYPE_ALIGNMENT(IOCTL_STRUC) );
Автоматические исправления исключений выравнивания режима ядра отключены для систем Intel Itanium.
Будьте осторожны с операциями NOT. Рассмотрим следующий пример.
UINT_PTR a; ULONG b; a = a & ~(b - 1);
Проблема заключается в том, что ~(b–1) создает "0x0000 0000 xxxx xxxx", а не "0xFFFF FFFF xxxx xxxx xxxx". Компилятор не обнаружит этого. Чтобы устранить эту проблему, измените код следующим образом:
a = a & ~((UINT_PTR)b - 1);
Будьте внимательны при выполнении неподписанных и подписанных операций. Рассмотрим следующий пример.
LONG a; ULONG b; LONG c; a = -10; b = 2; c = a / b;
Результат неожиданно большой. Правило заключается в том, что если один из операндов не подписан, результатом будет unsigned. В предыдущем примере преобразуется в неподписаемое значение, делимое на b, и результат, хранящийся в c. Преобразование не предполагает числовых манипуляций.
В качестве другого примера рассмотрим следующее:
ULONG x; LONG y; LONG *pVar1; LONG *pVar2; pVar2 = pVar1 + y * (x - 1);
Проблема возникает из-за того, что x является неподписанным, что делает все выражение неподписанным. Это работает нормально, если y не является отрицательным. В этом случае y преобразуется в неподписаемое значение, выражение вычисляется с использованием 32-разрядной точности, масштабируется и добавляется в pVar1. 32-разрядное отрицательное число без знака становится большим 64-разрядным положительным числом, что дает неправильный результат. Чтобы устранить эту проблему, объявите x как значение со знаком или явно введите его в long в выражении.
Будьте осторожны при выполнении поэтапного выделения размера. Пример:
struct xx { DWORD NumberOfPointers; PVOID Pointers[100]; };
Следующий код неверен, так как компилятор будет заполнять структуру дополнительными 4 байтами для выравнивания по 8 байтам:
malloc(sizeof(DWORD) + 100*sizeof(PVOID));
Следующий код является правильным:
malloc(offsetof(struct xx, Pointers) + 100*sizeof(PVOID));
Не передайте
(HANDLE)0xFFFFFFFF
в такие функции, как CreateFileMapping. Вместо этого используйте INVALID_HANDLE_VALUE.Используйте правильные описатели формата при печати строки. Используйте %p для вывода указателей в шестнадцатеричном формате. Это лучший выбор для печати указателей. Microsoft Visual C++ поддерживает %I для печати полиморфных данных. Visual C++ также поддерживает %I64 для печати 64-разрядных значений.