Страница 76 из 93 69. Не делайте предположений о размерах.
Классической проблемой является код, исходящий из того, что тип int имеет размер 32 бита. Следующий фрагмент не работает, если у вас 32-битный указатель и 16-битный тип int (что может быть при архитектуре Intel 80x86): double a[1000], *p = a; // ... dist_from_start_of_array_in_bytes = (int)p - (int)a; расстояние_от_начала_массива_в_байтах = (int)p - (int)a; Более трудно уловима такая проблема в С (но не в С++): g() { не_работает( 0 ); } не_работает( char *p ) { if( !p ) // вероятно не работает // ...}Компилятор соглашается с этим вызовом, потому что в С разрешены ссылки вперед (и не разрешены в С++, так что там это не проблема). 0 это тип int, поэтому в стек помещается 16-битовый объект. Но функция ожидает 32-битный указатель, поэтому она использует 16 бит из стека и добавляет к ним еще 16 бит всякого мусора для создания 32-битного указателя. Вероятнее всего, что if( !p ) даст ложный результат, так как только 16 бит из 32 будут равны 0. Традиционное решение состоит в использовании typedef : typedef int word; // всегда 16 бит typedef long dword; // всегда 32 бита. После чего вы можете поменять операторы typedef в новой операционной среде, чтобы гарантировать, что word по прежнему имеет размер 16 бит, а dword - 32 бита. Для 32-разрядной системы предыдущее может быть переопределено как: typedef short word; // всегда 16 бит typedef int dword; // всегда 32 бита. Другая связанная с размерностью часовая бомба спрятана в том способе, которым в ANSI С обеспечивается работа с иностранными языками. ANSI С определяет тип wchar_t для работы с расширенными наборами символов типа Unicode - нового 16-битного многонационального набора символов. Стандарт ANSI С также утверждает, что перед строкой с расширенными символами должен стоять символ L. Micrisoft и другие поставщики компиляторов стараются помочь вам писать переносимые программы, предусматривая макросы типа: #ifdef _UNICODE typedef wchar_t _TCHAR # define _T(x) L##x #else typedef char _TCHAR # define _T(x) x #endif Если константа _UNICODE не определена, то оператор: _TCHAR *p = _T("делай_что_нужно");имеет значение: char *p = "делай_что_нужно";Если константа _UNICODE определена, тот же самый оператор получает значение: wchar_t *p = L"делай_что_нужно";Пока все хорошо. Вы теперь можете попробовать перенести вашу старую программу в среду Unicode, просто используя свой редактор для замены всех экземпляров char на _TCHAR и помещения всех строковых констант в скобки _T(). Проблема состоит в том, что такой код, как ниже (в котором все _TCHAR первоначально были типа char), более не работает: _TCHAR str[4]; // ... int max_chars = sizeof(str); // предполагает, что тип char имеет размер 1 байт Тип _TCHAR будет иметь размер 2 байта при определенной константе _UNICODE, поэтому число символов у вас будет определено в два раза большим, чем есть на самом деле. Для исправления ситуации вы должны воспользоваться следующим вариантом: int max_chars = sizeof(str) / sizeof(*str) ; |