Предупреждающие сообщения компилятора
Предупреждающие сообщения компилятора для этого фрагмента кода отчетливо демонстрируют неявное предположение о том, что размер указателя составляет 4 байта.
SORTMM.C(137) : warning C4312: 'type cast' : conversion from 'DWORD' to 'TCHAR __based(pInFile) *' of greater size
SORTMM.C(139) : warning C4311: 'type cast' : pointer truncation from 'TCHAR __based(pInFile) *' to 'DWORD'
Первое предупреждение (строка 137) является существенным. Разыменование рХ после его приведения (type cast) к типу LPDWORD приводит к 32-битовому значению, которое затем назначается указателю pIn. Почти с полной уверенностью можно утверждать, что разыменование pIn вызовет исключение или приведет к возникновению иной серьезной ошибки. Правильным решением для строки 137 будет замена приведения к типу LPDWORD приведением к типу указателя LPTSTR следующим образом:
pIn = (TCHAR _based(pInFile)*)*(DWORD_PTR)pX;
Сообщение для строки 139 довольно интересно, поскольку мы сравниваем базовый указатель с размером файла. Если предположить, что файл не является гигантским, то на это предупреждение можно не обращать внимания. При этих условиях можно было бы проигнорировать и сообщение для строки 137. Однако мы учтем перспективу и приготовимся к работе с гигантскими файлами, пусть даже типом FsSize пока и является DWORD. Допуская полный диапазон значений указателя, мы должны преобразовать строку 139 следующим образом:
while ((*pIn != CR || *(pIn + 1) != LF) && (SIZE_T)pIn < (SIZE_T)FsIn) {
Второй сегмент, относящийся к шагу 2b, порождает дополнительные предупреждающие сообщения, связанным с усечением типов (pointer truncation). Соответствующий фрагмент кода представлен в программе 16.2.
Программа 16.2. sortMM: код до подготовки к переносу в Win64, часть 2
…
40 DWORD, KStart, KSize;
174 /* Шаг 2b: Получить первый ключ; определить размер и начальный адрес ключа. */
176 KStart = (DWORD) pInScan;
177 /* Вычисляем адрес начала поля ключа. */
178 while (*pInScan !=''&& *pInScan != '\t') pInScan++;
179 /* Вычисленный конец поля ключа. */
181 KSize = ((DWORD)pInScan – KStart) / TSIZE;
Компилятор выводит следующие предупреждающие сообщения:
SORTMM.C(176) : warning C4311: 'type cast' : pointer truncation from 'TCHAR __based(pInFile) *' to 'DWORD'
SORTMM.C(181) : warning C4311: 'type cast' : pointer truncation from 'TCHAR __based(pInFile) *' to 'DWORD'
Исправления сводятся к использованию DWORD_PTR в качестве типа данных в строке 40 и при приведении типов в строках 176 и 181.
Дополнительные сообщения такого же характера появляются на шаге 2с в конце функции CreateIndexFile. На Web-сайте книги находится видоизмененный файл sortMM64.с, который пригоден как для Win32, так и для Win64, и использование которого позволяет избавиться от появления предупреждающих сообщений.