правильно пользоваться указателями - не юзать ++ ?
От:
Аноним
Дата:
08.11.09 04:15
Оценка:
Всем пример!
чтобы программа никогда не падала — не использовать оператор ++ для указателя?
допустим нам нужно подсчитать сколько пробелов в строке.
char *buf = "hello word!";
будет ли безопасно использоватьуказатель так:
size_t count_space_symbols = 0;
char *end_buf = buf + strlen(buf) [b]- 1[b]; // указывает на последний символ в строкеwhile (buf <= end_buf)
{
if (*buf++ == ' ')
count_space_symbols ++;
}
По моему — нет. допустим в среде размер указателей 32 бита. end_buf может указывать на адрес 2147483647 (или не может?), а так как while(buf<=end_buf) и после buf инкрементируется то, он всегда будет меньше либо равно end_buf.
Но можно переписать так:
while (buf <= end_buf)
{
if (*buf == ' ')
count_space_symbols ++;
if (buf == end_buf)
break;
buf ++;
}
но увеличивается время выполнения программы. что не хорошо.
придется делать так?:
size_t len = strlen(buf);
for(size_t index=0; index<len; index++) {
if (buf[index] == ' ')
count_space_symbols ++;
}
Все верно?
или может можно как-то обойтись без "индексов"?
Re: правильно пользоваться указателями - не юзать ++ ?
Указатели на один элемент после последнего элемента массива разрешены, иначе STL не могла бы работать с указателями. По стандарту искать по "one past".
Русский военный корабль идёт ко дну!
Re: правильно пользоваться указателями - не юзать ++ ?
Как вариант — переложить заботу об указателях на стандартую библиотеку — в большинстве случаев это оправдано, к тому же упрощает код и таким образом минимизирует к-во багов
Здравствуйте, armani, Вы писали:
A>Как вариант — переложить заботу об указателях на стандартую библиотеку — в большинстве случаев это оправдано, к тому же упрощает код и таким образом минимизирует к-во багов
A>
std::string buf("hello world!");
A> int spaces = std::count_if(buf.begin(), buf.end(), isspace);
A>
Дабы не копировать почём зря строку,
const char str[] = "hello";
int spaces = std::count_if(str, str+sizeof(str), isspace); // для char sizeof корректен, для любых символов надо _countof
Или, как в исходном условии, вместо sizeof пишем strlen.
Re[3]: правильно пользоваться указателями - не юзать ++ ?
Здравствуйте, makdak, Вы писали:
M>а может есть авторы которые об этом пишут?
Может есть, мне не подадались.
Вообще, про код в исходном сообщении я не вполне уверен.
В STL принято писать так:
char *past_end_buf = buf + strlen(buf); // указывает после конца строки, 5.7/5while (buf != past_end_buf ) // 5.10/1 отсылает к 3.9.2/3, всё должно работать
{
}
Про то, что сравнение buf <= past_end_buf из исходного кода должно возвращать false, кода слева указатель после конца масива, я не нашел. Но для указатель является random access iterator, об этом указано и в стандарте и учебниках по STL, а для random access итератор все операции сравнения должны работать.
эта (древняя) практика называется loop unrolling -- может даже использоваться компиляторами для оптимизации циклов... но приводит к увеличению размера кода.
Re[2]: правильно пользоваться указателями - не юзать ++ ?
Здравствуйте, zaufi, Вы писали:
Z>а если подумать то вот так должно быть совсем быстро
Z>[ccode] Z>end_buf = buf + parse_str_len;
Всегда мне казалось, что для получения длины строки в Си, надо по ней пробежаться до конца. Соответственно какая может быть быстрота, если для вычисления мы по циклу уже пробежались, и начинаем снова бегать ? Я не верю, что оптимизатор настолько крут, что это отследит.
Re: правильно пользоваться указателями - не юзать ++ ?
Здравствуйте, Caracrist, Вы писали:
C>почему вот так работает почти в два раза быстрее: C>(кто не верит, проверяйте)
я думаю тут надо просто посчитать сколько занимает проверка и переход по циклу и сравнить просто с проверкой — тут скорее всего и есть разница в два раза.
Здравствуйте, Alexander G, Вы писали:
AG>Указатели на один элемент после последнего элемента массива разрешены, иначе STL не могла бы работать с указателями. По стандарту искать по "one past".
вот за это огромное спасибо.
а может есть авторы которые об этом пишут?
Здравствуйте, zaufi, Вы писали:
Z>эта (древняя) практика называется loop unrolling -- может даже использоваться компиляторами для оптимизации циклов... но приводит к увеличению размера кода.
O! даже название моей проблемы нарисовалось. а я голову ломал как спросить, спасибо, буду знать .
Re[4]: правильно пользоваться указателями - не юзать ++ ?
Здравствуйте, Alexander G, Вы писали:
AG>Про то, что сравнение buf <= past_end_buf из исходного кода должно возвращать false, кода слева указатель после конца масива, я не нашел. Но для указатель является random access iterator, об этом указано и в стандарте и учебниках по STL, а для random access итератор все операции сравнения должны работать.
мне оператора != хватит на все случаи жизни. Но всеравно б почитал что — нибуть на эту тему на русском.
Может кто поделится ссылкой?
Re[2]: правильно пользоваться указателями - не юзать ++ ?
Здравствуйте, armani, Вы писали:
A>Как вариант — переложить заботу об указателях на стандартую библиотеку — в большинстве случаев это оправдано, к тому же упрощает код и таким образом минимизирует к-во багов
A>
A>#include <string>
A>#include <algorithm>
A> // ...
A> std::string buf("hello world!");
A> int spaces = std::count_if(buf.begin(), buf.end(), isspace);
A>
+1, но stl не хватит на все случаи жизни.
Re[4]: правильно пользоваться указателями - не юзать ++ ?
AG>Ещё Duff's Device сделать можно
%) луче я думаю не запариваться и доверить компилятору раскрутку цикла (тямболее современные компиляторы это делают на раз -- сеня вот токо смотрел здесь
Здравствуйте, byleas, Вы писали:
B>Здравствуйте, armani, Вы писали:
B>Дабы не копировать почём зря строку, B>
const char str[] = "hello";
B>int spaces = std::count_if(str, str+sizeof(str), isspace); // для char sizeof корректен, для любых символов надо _countof
B>Или, как в исходном условии, вместо sizeof пишем strlen.
Только использование sizeof в таком варианте действительно полезно. Все остальные кто предлогал, так или иначе пользоваться strlen, просто незнают о чём говорят. Выполнение strlen это пустая трата времени для поиска нулевого символа, вместо того чтобы за ту же пробежку считать и пробелы.
Здравствуйте, Caracrist, Вы писали:
C>Здравствуйте, makdak, Вы писали:
M>>Здравствуйте, Caracrist, Вы писали:
C>>>конечно, тут же делаются кучя лишних операций
C>>>
M>>ну это понятно, а если строка не оканчивается 0? хотя Alexander G уже ответил. C>Либо на ноль, либо дан размер.
C>И что там "Alexander G уже ответил"? C>Вот это что ли: C>
C>char *past_end_buf = buf + strlen(buf);
C>
Alexander G ответил на сабж.
сколько ты еще будешь головой об стену биться?