Указатели должны указывать на адрес, больший, чем базовый для массива
Это правило подтверждено стандартом ANSI Си, но многие программисты, похоже, не подозревают о том способе, которым язык должен работать. ANSI Си говорит, что указатель может переходить на ячейку, следующую после окончания массива, но он не может иметь величину меньше, чем базовый адрес массива. Нарушение этого правила может прервать программу, которую пытаются выполнить, например, в сегментной модели памяти процессоров 80x86. Следующий код не будет работать:
int array[ SIZE ];
int *p = array + SIZE; // Здесь все в порядке; вы можете
// двигаться дальше.
while ( --p = array ) // Это не работает - возможен
// бесконечный цикл.
//...
Проблема состоит в том, что при сегментной архитектуре есть возможность того, что массив попадет на начало сегмента и получит исполнительный адрес 0x0000. (В архитектуре 8086 это будет смещением —
частью адреса любого байта, состоящего из адреса сегмента и смещения). Если p
установлен на начало массива (0x0000), то операция --p
вызывает его перемещение на адрес 0xfffe
(если у типа int
размер 2 байта), который считается большим, чем p. Другими словами, предыдущий цикл никогда не закончится. Исправьте эту ситуацию следующим образом:
while ( --p = array )
{
// ...
if ( p == array )
break;
}
Вы можете выйти из положения так:
int *p = array + (SIZE - 1);
do
{
// ...
} while ( p-- array );
но позаботьтесь, чтобы p был внутри массива перед началом цикла. (Указатель должен быть инициализирован значением p+(SIZE-1), а не p+SIZE).