![]() |
|
Модераторы: bsa |
![]()
|
|
| NoviceF |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 313 Регистрация: 13.3.2012 Где: Ростов-на-Дону Репутация: 2 Всего: 2 |
Вот у Липпмана в книжке есть такой пример с описанием:
"Если возвращенный указатель равен адресу &ia[6] (который расположен за последним элементом массива), то поиск оказался безрезультатным, в противном случае значение найдено". Но у меня как-то в памяти закрепилось, что обращение к памяти "за последним элементом массива" не влечёт за собой ничего хорошего.. Или данный приём является нормальной практикой и не грозит неопределённым поведением? Беглый поиск по интернетам и форуму мне не помог. |
|||
|
||||
| 586 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2243 Регистрация: 8.5.2006 Репутация: 8 Всего: 146 |
Ничего страшного не произойдёт, т. к. по этому индексу ничего не пишется и не читается.
То же самое и при использовании итераторов STL контейнеров:
Итератор v.begin() ведёт себя как правильный указатель, и по нему можно прочитать значение, а вот чтение или запись с помощью итератора v.end() приведёт к ошибке. Это сообщение отредактировал(а) 586 - 25.9.2012, 01:18 |
|||
|
||||
| feodorv |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Это было бы тогда так:
Вот разименовывание указателя *finishPtr и есть обращение к памяти. До разименовывания указатель представляет собой просто переменную, с целочисленным значением (по сути, номер байта в памяти процесса), 32-битную или 64-битную. Поэтому указателям можно присваивать произвольные значения (например, NULL), можно их сравнивать друг с другом и т.д. В Вашем примере функция find просто так написана, что в случае неудачи с поиском возвращает значение указателя, лежащего за пределами передаваемого ей массива, но это не значит, что внутри find происходит обращение по этому некорректному адресу. Почему в случае неудачи не возвращается NULL - это надо спросить Липпмана. Вы можете представить себе код функции find в таком виде:
Функция find при этом упрощена до предела. Обращения за пределы массива нет, хотя в случае неудачи возвращается указатель, не указывающий внутрь массива. Впрочем, здесь есть подводные камни. При вызове find значение аргумента finishPtr может не быть выровненной по границе четырёх (или восьми) байт, то есть ((unsigned int) finishPtr) % 4 != 0 (при этом полагаю, что startPtr - выровнена):
В этом коде уже заложена ошибка, связанная с тем, что число прочитанных из сокета (а это может быть и файл, и устройство, и всё что угодно) байт не соответствует целому числу ожидаемых интегеров, например, когда bytes равно 10. Тогда мало того, что find в случае неуспеха вернёт не тот указатель (&buf[12] вместо нами проверяемых &buf[10]), так ещё и может найти наше искомое значение в &buf[8], хотя значения buf[10] и buf[11] представляют собой мусор. Это сообщение отредактировал(а) feodorv - 25.9.2012, 01:45 -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||||
|
|||||||
| borisbn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 21 Всего: 135 |
> Почему в случае неудачи не возвращается NULL - это надо спросить Липпмана.
-------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
|||
|
||||
| NoviceF |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 313 Регистрация: 13.3.2012 Где: Ростов-на-Дону Репутация: 2 Всего: 2 |
По поводу контейнеров STL вопросов не возникало, т.к. об итераторе, указывающем на область за последним элементом контейнера, написано везде и много, а вот такого обращения с массивами в книгах я не встречал, или не обращал внимания. Вот что касается того, что речь идёт именно об индексе, который в действительности никак не влияет на память, этого я не увидел, почему-то сразу подумалось (сам додумал, чего в коде не написано Спасибо. Добавлено @ 08:19 feodorv, спасибо за объяснения. Это сообщение отредактировал(а) NoviceF - 25.9.2012, 08:22 |
||||
|
|||||
| borisbn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 21 Всего: 135 |
На самом деле find (впрочем, как и другие алгоритмы STL) работает не с итераторами, а с шаблонными параметрами, которые поддерживают операцию разыменования (*it), операцию ++ и сравнения друг с другом. Под эти требования замечательно подходят указатели, а итераторы просто имитируют поведение указателей.
и ещё. рекомендую делать не так а так
if ( presult != ia + ia_count ) { OK } else { BAD } думаю, понятно почему. -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
|||
|
||||
| NoviceF |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 313 Регистрация: 13.3.2012 Где: Ростов-на-Дону Репутация: 2 Всего: 2 |
Если бы для меня всё было так очевидно |
||||
|
|||||
| borisbn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 21 Всего: 135 |
нет. это защита от того, что завтра ты изменишь размер массива -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
|||
|
||||
| xvr |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 35 Всего: 223 |
Стандарт С++, глава 5.7 Additive operators:
|
|||
|
||||
| feodorv |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Чешу репу. Что значит "валидный указатель" в данном контексте? Я понял отрывок так, что если вычислить указатель Q, равный P плюс несколько элементов массива, то получим указатель, значение которого больше значения P, даже если Q станет смотреть сразу за границу массива. Если же переборщить, то может произойти переполнение значения Q, и Q может стать меньше P. Возможно, такое понимание является игрой моего воображения, поправьте, если чо... -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
|||
|
||||
| xvr |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 35 Всего: 223 |
Насколько я понимаю, имелось в виду следующее. Если у нас есть массив типа int a[10];, то мы можем свободно использовать в адресной арифметике указателями от &a[0] до &a[10] включительно. При этом будут получаться указатели с вполне ожидаемым поведением (в том числе и ожидаемыми результатами их сравнения). Если же мы попытаемся вычислить &a[11] - то это уже UB Добавлено через 1 минуту и 17 секунд
Более того, он вполне может стать чем угодно, NULL например |
|||
|
||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
Проще говоря, на 16-ти битных платформах можно создать массив из 65535 чаров. При этом индекс 65535 валиден, но выходит за границу массива. Следующий же индекс должен быть 65536, но будет 0. А это уже валидный индекс внутри массива. В итоге, программа его использующая, будет работать не так, как ожидалось.
|
|||
|
||||
| maxim1000 |
|
||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 1 Всего: 110 |
в новом стандарте можно даже так:
-------------------- qqq |
||||
|
|||||
| feodorv |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
xvr, bsa, спасибо!
Именно так я и понял))) Речь идёт именно о неожиданном переполнении значения указателя. Пока значение указателя не переполнилось, мы можем спокойно его сравнивать с другим указателем. Иначе - сюрприз. Вот. Сочетание "валидный указатель", всё же, соотносится с понятием "разименовывание указателя", не? Гм. В плоской модели памяти поведение указателя при сдвиге предсказуемо, совсем "чем угодно" он стать не может))) И в этом смысле (void *) 4 ничуть не лучше или хуже чем просто NULL))) -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
|||
|
||||
| xvr |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 35 Всего: 223 |
||||
|
||||
![]()
|
| Правила форума "C/C++: Для новичков" | |
|
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |