правильно пользоваться указателями - не юзать ++ ?
От: Аноним  
Дата: 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: правильно пользоваться указателями - не юзать ++ ?
От: Alexander G Украина  
Дата: 08.11.09 08:24
Оценка: 3 (1) +1
Указатели на один элемент после последнего элемента массива разрешены, иначе STL не могла бы работать с указателями. По стандарту искать по "one past".
Русский военный корабль идёт ко дну!
Re: правильно пользоваться указателями - не юзать ++ ?
От: armani  
Дата: 08.11.09 10:00
Оценка: 3 (1) +1
Как вариант — переложить заботу об указателях на стандартую библиотеку — в большинстве случаев это оправдано, к тому же упрощает код и таким образом минимизирует к-во багов

#include <string>
#include <algorithm>

    // ...

    std::string buf("hello world!");
    int spaces = std::count_if(buf.begin(), buf.end(), isspace);
Re[2]: правильно пользоваться указателями - не юзать ++ ?
От: byleas  
Дата: 12.11.09 19:50
Оценка: 10 (1)
Здравствуйте, 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]: правильно пользоваться указателями - не юзать ++ ?
От: Alexander G Украина  
Дата: 08.11.09 09:58
Оценка: 3 (1)
Здравствуйте, makdak, Вы писали:

M>а может есть авторы которые об этом пишут?


Может есть, мне не подадались.

Вообще, про код в исходном сообщении я не вполне уверен.
В STL принято писать так:

char *past_end_buf = buf + strlen(buf); // указывает после конца строки, 5.7/5
while (buf != past_end_buf ) // 5.10/1 отсылает к 3.9.2/3, всё должно работать
{

}

(ссылки по черновику http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf , возможно в действующем стандарте не такая нумерация)

Про то, что сравнение buf <= past_end_buf из исходного кода должно возвращать false, кода слева указатель после конца масива, я не нашел. Но для указатель является random access iterator, об этом указано и в стандарте и учебниках по STL, а для random access итератор все операции сравнения должны работать.
Русский военный корабль идёт ко дну!
Re[3]: Этюд :)
От: zaufi Земля  
Дата: 08.11.09 12:04
Оценка: 3 (1)
эта (древняя) практика называется loop unrolling -- может даже использоваться компиляторами для оптимизации циклов... но приводит к увеличению размера кода.
Re[2]: правильно пользоваться указателями - не юзать ++ ?
От: makdak  
Дата: 08.11.09 09:10
Оценка: :)
Здравствуйте, Caracrist, Вы писали:

C>
C>char * c = buf; 
C>while (*c != '\0')
C>{
C>    if (*c == ' ')
C>        count_space_symbols++;
C>    c++;
C>}
C>



end_buf = buf + parse_str_len;
while (buf != end_buf)
{
     if (*buf++ == ' ')
        count_space_symbols++;
}

а так еще быстрей будет, не будет тратиться время на разименновывание.
Re[3]: правильно пользоваться указателями - не юзать ++ ?
От: zaufi Земля  
Дата: 09.11.09 15:22
Оценка: -1
Здравствуйте, makdak, Вы писали:

а если подумать то вот так должно быть совсем быстро

end_buf = buf + parse_str_len;
while (buf != end_buf)
{
    count_space_symbols += int(*buf++ == ' ');
}
Re[4]: правильно пользоваться указателями - не юзать ++ ?
От: elmal  
Дата: 09.11.09 19:29
Оценка: +1
Здравствуйте, zaufi, Вы писали:

Z>а если подумать то вот так должно быть совсем быстро


Z>[ccode]

Z>end_buf = buf + parse_str_len;
Всегда мне казалось, что для получения длины строки в Си, надо по ней пробежаться до конца. Соответственно какая может быть быстрота, если для вычисления мы по циклу уже пробежались, и начинаем снова бегать ? Я не верю, что оптимизатор настолько крут, что это отследит.
Re: правильно пользоваться указателями - не юзать ++ ?
От: Caracrist https://1pwd.org/
Дата: 08.11.09 05:47
Оценка:
Здравствуйте, Аноним, Вы писали:

А>
А>while (buf <= end_buf)
А>{
А>    if (*buf == ' ')
А>        count_space_symbols ++;

А>    if (buf == end_buf)
А>        break;

А>    buf ++;
А>}
А>


А>но увеличивается время выполнения программы. что не хорошо.


конечно, тут же делаются кучя лишних операций

char * c = buf; 
while (*c != '\0')
{
    if (*c == ' ')
        count_space_symbols++;
    c++;
}
~~~~~
~lol~~
~~~ Single Password Solution
Re[2]: Этюд :)
От: Caracrist https://1pwd.org/
Дата: 08.11.09 06:35
Оценка:
C>
C>char * c = buf; 
C>while (*c != '\0')
C>{
C>    if (*c == ' ')
C>        count_space_symbols++;
C>    c++;
C>}
C>


почему вот так работает почти в два раза быстрее:
(кто не верит, проверяйте)
        char * c = buf; 
        while (*c != '\0')
        {
            if (*c == ' ')
                count_space_symbols++;
            if(*(++c) != '\0')
            {
                if (*c == ' ')
                    count_space_symbols++;
                if(*(++c) != '\0')
                {
                    if (*c == ' ')
                        count_space_symbols++;
                } else break;
            } else break;
            c++;
        }
~~~~~
~lol~~
~~~ Single Password Solution
Re[3]: Этюд :)
От: Alex Dav Россия  
Дата: 08.11.09 08:10
Оценка:
Здравствуйте, Caracrist, Вы писали:

C>почему вот так работает почти в два раза быстрее:

C>(кто не верит, проверяйте)

я думаю тут надо просто посчитать сколько занимает проверка и переход по циклу и сравнить просто с проверкой — тут скорее всего и есть разница в два раза.
Re[4]: Этюд :)
От: Alex Dav Россия  
Дата: 08.11.09 08:19
Оценка:
Кстати, кто подскажет как перейти в студии на отладку в ассемлер код?
Re[5]: Этюд :)
От: Тот кто сидит в пруду Россия  
Дата: 08.11.09 08:23
Оценка:
Здравствуйте, Alex Dav, Вы писали:

AD>Кстати, кто подскажет как перейти в студии на отладку в ассемлер код?


Alt+8
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[2]: правильно пользоваться указателями - не юзать ++ ?
От: makdak  
Дата: 08.11.09 08:43
Оценка:
Здравствуйте, Caracrist, Вы писали:

C>конечно, тут же делаются кучя лишних операций


C>
C>char * c = buf; 
C>while (*c != '\0')
C>{
C>    if (*c == ' ')
C>        count_space_symbols++;
C>    c++;
C>}
C>


ну это понятно, а если строка не оканчивается 0? хотя Alexander G уже ответил.

Alex Dav кищ отсюда флудер.
Re[2]: правильно пользоваться указателями - не юзать ++ ?
От: makdak  
Дата: 08.11.09 08:51
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Указатели на один элемент после последнего элемента массива разрешены, иначе STL не могла бы работать с указателями. По стандарту искать по "one past".


вот за это огромное спасибо.
а может есть авторы которые об этом пишут?
Re[4]: Этюд :)
От: makdak  
Дата: 09.11.09 03:42
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>эта (древняя) практика называется loop unrolling -- может даже использоваться компиляторами для оптимизации циклов... но приводит к увеличению размера кода.


O! даже название моей проблемы нарисовалось. а я голову ломал как спросить, спасибо, буду знать .
Re[4]: правильно пользоваться указателями - не юзать ++ ?
От: makdak  
Дата: 09.11.09 03:47
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Про то, что сравнение buf <= past_end_buf из исходного кода должно возвращать false, кода слева указатель после конца масива, я не нашел. Но для указатель является random access iterator, об этом указано и в стандарте и учебниках по STL, а для random access итератор все операции сравнения должны работать.


мне оператора != хватит на все случаи жизни. Но всеравно б почитал что — нибуть на эту тему на русском.
Может кто поделится ссылкой?
Re[2]: правильно пользоваться указателями - не юзать ++ ?
От: makdak  
Дата: 09.11.09 03:49
Оценка:
Здравствуйте, 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]: правильно пользоваться указателями - не юзать ++ ?
От: Alexander G Украина  
Дата: 09.11.09 15:24
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>а если подумать то вот так должно быть совсем быстро


Z>
Z>end_buf = buf + parse_str_len;
Z>while (buf != end_buf)
Z>{
Z>    count_space_symbols += int(*buf++ == ' ');
Z>}
Z>


Ещё Duff's Device сделать можно
Русский военный корабль идёт ко дну!
Re[5]: правильно пользоваться указателями - не юзать ++ ?
От: zaufi Земля  
Дата: 09.11.09 15:30
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Здравствуйте, zaufi, Вы писали:


Z>>а если подумать то вот так должно быть совсем быстро


Z>>
Z>>end_buf = buf + parse_str_len;
Z>>while (buf != end_buf)
Z>>{
Z>>    count_space_symbols += int(*buf++ == ' ');
Z>>}
Z>>


AG>Ещё Duff's Device сделать можно

%) луче я думаю не запариваться и доверить компилятору раскрутку цикла (тямболее современные компиляторы это делают на раз -- сеня вот токо смотрел здесь
Автор: zaufi
Дата: 09.11.09
) ...
читаемость кода сохраницо по кр мере
Re[3]: правильно пользоваться указателями - не юзать ++ ?
От: Caracrist https://1pwd.org/
Дата: 15.11.09 05:49
Оценка:
Здравствуйте, 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 это пустая трата времени для поиска нулевого символа, вместо того чтобы за ту же пробежку считать и пробелы.
~~~~~
~lol~~
~~~ Single Password Solution
Re[3]: правильно пользоваться указателями - не юзать ++ ?
От: Caracrist https://1pwd.org/
Дата: 15.11.09 05:59
Оценка:
Здравствуйте, makdak, Вы писали:

M>Здравствуйте, Caracrist, Вы писали:


C>>конечно, тут же делаются кучя лишних операций


C>>
C>>char * c = buf; 
C>>while (*c != '\0')
C>>{
C>>    if (*c == ' ')
C>>        count_space_symbols++;
C>>    c++;
C>>}
C>>


M>ну это понятно, а если строка не оканчивается 0? хотя Alexander G уже ответил.

Либо на ноль, либо дан размер.

И что там "Alexander G уже ответил"?
Вот это что ли:

char *past_end_buf = buf + strlen(buf);

~~~~~
~lol~~
~~~ Single Password Solution
Re[4]: правильно пользоваться указателями - не юзать ++ ?
От: makdak  
Дата: 15.11.09 13:08
Оценка:
Здравствуйте, Caracrist, Вы писали:

C>Здравствуйте, makdak, Вы писали:


M>>Здравствуйте, Caracrist, Вы писали:


C>>>конечно, тут же делаются кучя лишних операций


C>>>
C>>>char * c = buf; 
C>>>while (*c != '\0')
C>>>{
C>>>    if (*c == ' ')
C>>>        count_space_symbols++;
C>>>    c++;
C>>>}
C>>>


M>>ну это понятно, а если строка не оканчивается 0? хотя Alexander G уже ответил.

C>Либо на ноль, либо дан размер.

C>И что там "Alexander G уже ответил"?

C>Вот это что ли:
C>

C>char *past_end_buf = buf + strlen(buf);

C>
Alexander G ответил на сабж.
сколько ты еще будешь головой об стену биться?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.