Добавление указателей со значением типа size_t

class CheckPointer {
public:
CheckPointer(int * mbeg, int * mend) :
beg(mbeg), end(mend), curr(mbeg) {}

// subscript operator
int & operator[] (const size_t pos) {
if (beg + pos < beg) {
throw out_of_range("ERR: before beg!");
}
if (beg + pos >= end)
throw out_of_range("ERR: end or past end!");
return *(const_cast<int *>(beg + pos));
}
private:
const int * beg;
const int * end;
int * curr;
};

Я определил оператор индекса для класса CheckPointer. Поскольку @param pos имеет тип size_t, я не могу проверить, передал ли пользователь положительное или отрицательное значение. Однако я пытаюсь написать код для проверки границ, и он работает:

        if (beg + pos < beg) {
throw out_of_range("ERR: before beg!");
}

Я не знаю, почему это работает … Кто-нибудь может мне помочь?

Спасибо за рассмотрение моего вопроса!


Для дополнительной информации:

Окружение: затмение CDT, Ubuntu 10.04

тест-код:

int iarr[6] = {1, 2, 3, 4, 5, 6};
CheckPointer cp(iarr, iarr+6);
// subscript
cout << cp[2] << endl;
cout << cp[5] << endl;
cout << cp[-2] << endl; // error: before beg

тест-code_output:

terminate called after throwing an instance of 'std::out_of_range'
what():  ERR: before beg!
3
6

1

Решение

Это работает, потому что отрицательное значение приведено к значению без знака. Архитектура вашей машины, вероятно, использует два дополнения для отрицательных значений, поэтому значение -2 приводит к:

0xfffffffe (assuming 32-bit)

Когда вы добавляете это к begоборачивается и предоставляется beg больше или равно 2, имеет эффект вычитания 2 из него. Таким образом, несмотря на то, что индекс чрезвычайно велик, он по существу выполнил вычитание. Если значение beg было 1 или же 0вместо этого ошибка будет «за концом».

2

Другие решения

Формально, сравнивая beg + pos в beg имеет неопределенное поведение, если beg + pos находится за пределами массива, который начинается в beg (это немного упрощено, но достаточно для этого обсуждения). Лучшая проверка для плохого индекса была бы:

if (end - beg <= pos)

Но это не отвечает на вопрос. Преобразование небольших отрицательных значений в size_t производит большие положительные значения; обработка их как смещения дает указатель, который находится далеко за концом массива, поэтому проверка, находится ли результат в границах, найдет эту проблему, а также «обычные» значения, которые просто выходят за пределы.

1

По вопросам рекламы [email protected]