Это неправильный for! Классический for имеет вид forпеременная=началоtoконецstepшаг, а современный — forпеременнаяinколлекция.
> Но, на самом деле, гемор начинается чуть позже, когда тебе надо поитерировать массив с конца и с шагом step.
Здравствуйте, gegMOPO4, Вы писали:
MOP>Это неправильный for! Классический for имеет вид forпеременная=началоtoконецstepшаг, а современный — forпеременнаяinколлекция.
Мы ещё о С++,
MOP>Как ни странно, но на этот раз Сыроежка прав.
Прав в чём? В том, что надо везде тулить беззнаковые? Я тк не считаю.
И циклы for со сдвигами итератора в проверке условия мне тоже не нравятся...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
22.02.12 14:04, Erop написав(ла): > Здравствуйте, gegMOPO4, Вы писали: > MOP>Это неправильный for! Классический for имеет вид forпеременная=началоtoконецstepшаг, а современный — forпеременнаяinколлекция. > Мы ещё о С++,
Мы о for. В C for неправильный. Впрочем, можно и о C++. The range-based for statement.
> MOP>Как ни странно, но на этот раз Сыроежка прав. > Прав в чём? В том, что надо везде тулить беззнаковые? Я тк не считаю.
В том, что идиоматичная итерация по беззнаковому назад в C++ выглядит так.
Здравствуйте, gegMOPO4, Вы писали:
MOP>В том, что идиоматичная итерация по беззнаковому назад в C++ выглядит так.
IMHO, это while...
Он, кстати, так и написал на автомате
В любом случае, IMHO, цельная концепция выглядит так, что for в обе стороны пишется ОДИНАКОВО, а индекс используется знаковый...
for( int i = 0; i < N; i++ ){}
for( int i = N-1; i >= 0; i-- ){}
Но другие подходы тое применяются, конечно...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
22.02.12 15:04, Erop написав(ла): > Здравствуйте, gegMOPO4, Вы писали: > MOP>В том, что идиоматичная итерация по беззнаковому назад в C++ выглядит так. > IMHO, это while...
Да, напрасно в Си ввели такой for.
> В любом случае, IMHO, цельная концепция выглядит так, что for в обе стороны пишется ОДИНАКОВО, а индекс используется знаковый... >
for( int i = 0; i< N; i++ ){}
> for( int i = N-1; i>= 0; i-- ){}
Ну-ка, как посчитать от трёх миллиардов вниз на 32-битных целых? Детская ошибка.
Здравствуйте, gegMOPO4, Вы писали:
MOP>Ну-ка, как посчитать от трёх миллиардов вниз на 32-битных целых? Детская ошибка.
Никак не надо считать так долго.
ы правда считаешь, что стоит бороться за этот битик? Особенно, когда речь идёт, например, об итерации массива интов?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, gegMOPO4, Вы писали:
MOP>Да, напрасно в Си ввели такой for.
Может быть, но маемо шо маемо.
У меня в команде, например, принято писать for'ы так, что изменения параметра цикла могут быть толко в соответствующей части for'а. А в теле или в условии параметр менять не нельзя. И это правда повышает читабельность. От for'ов не ждёшь всяки хитрых ходов...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
23.02.12 00:00, Erop написав(ла): > Здравствуйте, gegMOPO4, Вы писали: > MOP>Ну-ка, как посчитать от трёх миллиардов вниз на 32-битных целых? Детская ошибка. > Никак не надо считать так долго. > ы правда считаешь, что стоит бороться за этот битик? Особенно, когда речь идёт, например, об итерации массива интов?
Здравствуйте, gegMOPO4, Вы писали:
MOP>Давным-давно, когда int был 16-битным…
Даже тогда ловить биты было себе дороже.
Если это не какой-то сверх-быстрый код, то верным решением всегда было "взять int подлиннее",
Если тебе надо считать миллиарды -- бери 64-битный, если десятки тысяч -- 32-битный и будет тебе счастье.
А от того, что ты один битик добавишь, счатье будет вс равно очен ненадёжным...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Аноним, Вы писали:
А>Приветствую.
А>- Меня вот всегда удивляло, почему в качестве счетчика цикла, который будет использоваться в качестве индексации масива / контейнера, зачастую используется знаковая целочисленная переменная?
А>Нет, ну я понимаю, что size_t многим просто не нужен — пишу себе под 32 бита и буду писать, думают они.
А>А вот почему бы не написать unsigned int, к примеру — ума не приложу. Лень написать лишние буквы?
А>- Кстати, как часто, когда вы имеете дело с контейнерами, вы используете итераторы? Оператор индексации / метод at настолько же часто?
всегда пишу unsigned для типов смысл которых не подразумевает отрицательных значений (индекс в массиве, число элементов, счетчик чегоньть, etc) либо нет особой разницы в применении между знаковым и беззнаковым числом (например когда требуется какойнить случайный ID). правда большинство циклов все таки у меня используют итераторы или range based for, который стал вытеснять применение всяких алгоритмов из std (for_each, transform, find_if, etc) -- ибо запись стала проще.
что касается применения unsigned счетчиков в циклах, кроме "эстетических" соображений есть еще и вполне практический: http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html
в данном руководстве утверждается, и есть мнение что не безосновательно , что применение unsigned типов идет только на пользу!
в частности читать нужно со страницы 144 (абсолютный номер в этой PDF, а не по index'у): 3.4.2.2 Optimizing for Macro-fusion. и втыкать в частности пример на странице 146...
А>- Допустим, нам надо выделить два одинаковых по размеру куска памяти одного и того же типа.
вот это зависит от того где будет находится данный код -- если внутри небольшого класса и lifetime обоих кусков будет одинаков, и наружу ничего "светиться" не будет, и есть требования по скорости\памяти -- отчего бы нет... во всех остальных случаях -- *НАХЕРНАДО*. (от этого кода за версту несет потенциальными проблемами)
Здравствуйте, zaufi, Вы писали:
>>>всегда пишу unsigned для типов смысл которых не подразумевает отрицательных значений (индекс в массиве, число элементов, счетчик чегоньть, etc)
хмм индекс массива иногда имеет смысл как знаковый и
бывает испрользуется при обработке массивов например
p[-1] p[-2] разумеется p это указатель а
не сам массив разумеется если индексировать сам массив
то знак бессмыслен поскольку он всегда ссылается на базу
а вот через указатель уже и знаковый индекс пригодится
сам пишу или int или UINT или size_t а вот unsigned int просто тупо лень больше букв
да и не нужно так как обрабатывается заведомо небольшой диапазон да и не припомню что бы надо было обрабатывать такие огромные диапазоны где бы int не хватило если это только не библиотека общего пользования которую надо делать с расчетом на максимальные нагрузки но такой код сильно отличается от того что мы пишем каждый день потому что в отличии от библиотеки общего пользования мы знаем предельные нагрузки и почти всегда хватает простого int выше крыши
согласен можно писать и unsigned int если не лень но смысла в этом не вижу
Здравствуйте, jyuyjiyuijyu, Вы писали:
J>Здравствуйте, zaufi, Вы писали:
>>>>всегда пишу unsigned для типов смысл которых не подразумевает отрицательных значений (индекс в массиве, число элементов, счетчик чегоньть, etc)
J>хмм индекс массива иногда имеет смысл как знаковый и J>бывает испрользуется при обработке массивов например
J>p[-1] p[-2] разумеется p это указатель а J>не сам массив разумеется если индексировать сам массив J>то знак бессмыслен поскольку он всегда ссылается на базу J>а вот через указатель уже и знаковый индекс пригодится
ну да, С++ позволяет кучу странных "фишек"... но никогда-НИКОГДА мне не нужно было иметь отрицательные индексы в массиве!
а кому нужно было на практике?? не чисто умозрительно-теоретически или из академического интереса -- а реально в "боевом коде"??
по моему такой код будет слегка выламывать моск читающему и поэтому должен быть отрефачен, а руки у написавшего должны болеть от побоев...
чем отрицательные индексы, могут быть лучше при обходе массива чем положительные, начинающиеся с конца??? (забудем на секундочку о существовании std::string::npos -- говорим об алгоритмах обхода элементов типа for_each)... могу допустить, что с небольшой вероятностью где-то во вселенной существует хитрющий (т.е. оч не простой!) алгоритм, оч требовательный к скорости\памяти, и потому заоптимизорованный по самое нибалуй, где это в принципе может встретиться -- но в "обычной жизни"
J>сам пишу или int или UINT или size_t а вот unsigned int просто тупо лень больше букв
ну для начала можно просто писать "unsigned" -- то что он int, в таком случае подразумевается... а во-вторых, может надо завести редактор приличный??? мой вот после нажатия 3х символов "uns" комплитит мне это в требуемый "unsigned" -- поэтому для меня что "int", что "uns" -- все те же 3 буквы...
J>да и не нужно так как обрабатывается заведомо небольшой диапазон да и не припомню что бы надо было обрабатывать такие огромные диапазоны где бы int не хватило если это только не библиотека общего пользования которую надо делать с расчетом на максимальные нагрузки но такой код сильно отличается от того что мы пишем каждый день потому что в отличии от библиотеки общего пользования мы знаем предельные нагрузки и почти всегда хватает простого int выше крыши
да дело даже не в том, хватает или не хватает разрядности int/unsigned для хранения счетчика из 10ти элементов...
J>согласен можно писать и unsigned int если не лень но смысла в этом не вижу
... смысл в том, чтобы показать читающему, что беззнаковое значение переменной несет определенный смысл -- в частности, если говорить об индексах, мы намекаем читающему, что оно не может быть отрицательным! (а параноидально расставленными ассертами проверяем его валидность при всех операциях "до" и "после")... или там что количество элементов не собирается быть меньше нуля, так же как и количество килограмм картошки привезенной с поля не может быть -100500... -- разумеется в тех местах, где по смыслу это "нормально"... ибо, разумеется, для того чтобы посчитать какую-либо разницу велечин, которые by design не могут быть сами по себе отрицательные (вес предметов, геометрические размеры (по кр мере в нашей вселенной), и т.д.), конечно же нужно брать знаковые типы...
ну и второй смысл, как я уже говорил, помочь компилятору сделать более эффективный код -- если применение unsigned вместо int в качестве счетчика сделает мой код чуть быстрее (НАХАЛЯВУ!), конечно надо использовать!... даже если бы не было у меня автокомплита все равно писал бы unsigned (нахера экономить на 10^-3 секунды в написании -- печатать быстро я научилсо давно уже -- мне не в лом!)
ну да, С++ позволяет кучу странных "фишек"... но никогда-НИКОГДА мне не нужно было иметь отрицательные индексы в массиве!
а кому нужно было на практике?? не чисто умозрительно-теоретически или из академического интереса -- а реально в "боевом коде"??
по моему такой код будет слегка выламывать моск читающему и поэтому должен быть отрефачен, а руки у написавшего должны болеть от побоев...
чем отрицательные индексы, могут быть лучше при обходе массива чем положительные, начинающиеся с конца??? (забудем на секундочку о существовании std::string::npos -- говорим об алгоритмах обхода элементов типа for_each)... могу допустить, что с небольшой вероятностью где-то во вселенной существует хитрющий (т.е. оч не простой!) алгоритм, оч требовательный к скорости\памяти, и потому заоптимизорованный по самое нибалуй, где это в принципе может встретиться -- но в "обычной жизни"
ну вот я использовал и не раз отрицательные индексы например
часто во время парсинга текста есть указатель p который скачет
по строке например после операции p = strstr вот теперь
нам надо проверить что предыдущий символ это например #
если нет делаем что то другое тогда в общем получается
такой код
p = strstr(text, 'magic pattern')
if (p[-1] == '#')
else
иногда даже больше надо проверить не предшествующий а 2 — 3
символа до маски тогда получается такой код
p = strstr(text, 'magic pattern')
if (p[-1] == '#' && p[-2] == '@' && p[-3] == '%')
else
незнаю но мне кажется здесь очевидным использование отрицательных
индексов собственно только в похожих случаях я их и использую
за что тут надо бить по рукам ?
... смысл в том, чтобы показать читающему, что беззнаковое значение переменной несет определенный смысл -- в частности, если говорить об индексах, мы намекаем читающему, что оно не может быть отрицательным! (а параноидально расставленными ассертами проверяем его валидность при всех операциях "до" и "после")... или там что количество элементов не собирается быть меньше нуля, так же как и количество килограмм картошки привезенной с поля не может быть -100500... -- разумеется в тех местах, где по смыслу это "нормально"... ибо, разумеется, для того чтобы посчитать какую-либо разницу велечин, которые by design не могут быть сами по себе отрицательные (вес предметов, геометрические размеры (по кр мере в нашей вселенной), и т.д.), конечно же нужно брать знаковые типы...
не буду говорить за всех скажу за себя мне при чтении исходника
в последнюю очередь интересно знаковый индекс или нет тем более
мне и так есть на что обратить свое внимание а тут мне насильно
заставляют цеплятся глазами за эту особенность зачем эта лишняя
инфа ? ладно я понимаю когда это оправдано алгоритм заточен
под большие нагрузки но когда это массив из 10
элементов я считаю беззнаковость это лишняя информация
ну и второй смысл, как я уже говорил, помочь компилятору сделать более эффективный код -- если применение unsigned вместо int в качестве счетчика сделает мой код чуть быстрее (НАХАЛЯВУ!), конечно надо использовать!... даже если бы не было у меня автокомплита все равно писал бы unsigned (нахера экономить на 10^-3 секунды в написании -- печатать быстро я научилсо давно уже -- мне не в лом!)
оптимизация можеть быть но честно я не готов работать за компилятор мне лень
и такое микроускорение в моих программах не самое главное
P.S кстати всех с праздником с Днем защитника отечества!
Здравствуйте, Erop, Вы писали:
MOP>>Ну-ка, как посчитать от трёх миллиардов вниз на 32-битных целых? Детская ошибка. E>Никак не надо считать так долго. E>ы правда считаешь, что стоит бороться за этот битик? Особенно, когда речь идёт, например, об итерации массива интов?
Тут дело не в битиках, а в том, что стандартные контейнеры имеют размер выраженный через size_t. А ходить по массиву с индексом диапазон которого меньше размера мне не нравится из идеологических соображений. Поэтому я перешёл на итераторы.
Здравствуйте, jyuyjiyuijyu, Вы писали:
J>ну вот я использовал и не раз отрицательные индексы например J>часто во время парсинга текста есть указатель p который скачет J>по строке например после операции p = strstr вот теперь J>нам надо проверить что предыдущий символ это например # J>если нет делаем что то другое тогда в общем получается J>такой код
J>незнаю но мне кажется здесь очевидным использование отрицательных J>индексов собственно только в похожих случаях я их и использую J>за что тут надо бить по рукам ?
Здравствуйте, night beast, Вы писали:
NB>за пределы диапазона вылететь не боишься?
конечно боимся более того это самое мерзкое в
таких велосипедах поэтому тщательно вставляем
проверки просто я для примера упростил
а вообще меня самого тошнит от таких доморощенных
велосипедов но иногда приходится писать
p = strstr(text, 'magic pattern')
if (p != text)
if (p[-1] == '#')
else
p = strstr(text, 'magic pattern')
if (p - text >= 3)
if (p[-1] == '#' && p[-2] == '@' && p[-3] == '%')
else
Здравствуйте, B0FEE664, Вы писали:
BFE>Тут дело не в битиках, а в том, что стандартные контейнеры имеют размер выраженный через size_t. А ходить по массиву с индексом диапазон которого меньше размера мне не нравится из идеологических соображений. Поэтому я перешёл на итераторы.
Это же формальность? этот самый size_t можно реалтзовать только в случе ОЧЕНЬ БОЛЬШОГО массива char'ов...
IMHO, это крайне редкая ситуация, и на std::vector, например, не реализуемая, из-за его плитики переаллокации, например...
Хотя я согласен, что на STL лучше работать через итераторы, так как этого ждут авторы библиотеки и компилятора...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
BFE>>Тут дело не в битиках, а в том, что стандартные контейнеры имеют размер выраженный через size_t. А ходить по массиву с индексом диапазон которого меньше размера мне не нравится из идеологических соображений. Поэтому я перешёл на итераторы.
E>Это же формальность?
Разумеется. И следование формальным правилам — ценное качество для программиста.
E>этот самый size_t можно реалтзовать только в случе ОЧЕНЬ БОЛЬШОГО массива char'ов... E>IMHO, это крайне редкая ситуация, и на std::vector, например, не реализуемая, из-за его плитики переаллокации, например...
Ситуация редкая, но и память нынче дешевая. Что мешает написать:
try{
std::vector v;
v.reserv(N);// N - беззнаковое целое прочитанное из первого поля файла данных, возможно результат
// сериализации, которая учитывает размер поля на данной архитектуре "забив" на совместимость формата файлов.
}
catch (std::length_error& le) {
cerr << "Size Matters! It is too large!";
}
особенно если учесть, что часто оставляют int тридцатидвухбитным даже на 64-битной архитектуре.
Здравствуйте, B0FEE664, Вы писали:
E>>Это же формальность? BFE>Разумеется. И следование формальным правилам — ценное качество для программиста.
Ценное качество для любого инженера, в том числе и программиста -- думать головой и понимать что зачем и почему именно так он делает...
В данном случае имеет место быть размен — ошибки переполнения около нуля, против ошибок переполнения около бесконечности.
Ноль дрстижим всегда, а бесконечность, наоборот, удобно сделать недостижимой, правильно выбрав разрядность целых.
BFE>Ситуация редкая, но и память нынче дешевая. Что мешает написать:
BFE>
BFE> try{
BFE> std::vector v;
BFE> v.reserv(N);// N - беззнаковое целое прочитанное из первого поля файла данных, возможно результат
BFE> // сериализации, которая учитывает размер поля на данной архитектуре "забив" на совместимость формата файлов.
BFE> }
BFE> catch (std::length_error& le) {
BFE> cerr << "Size Matters! It is too large!";
BFE> }
BFE>
адресного пространства не хватит. Этомесли мы всё ещё о size_t...
Мало того, Нормальная программа должна бы, прочитав N из файла, проверить его, как минимум на неотрицательность...
BFE>особенно если учесть, что часто оставляют int тридцатидвухбитным даже на 64-битной архитектуре.
Это ещё больше намекает нам, что даже 32-битный int на практике переполнить трудно. но если таКой шанс есть, то надо брать не беззнаковую версию, а 64-битную!
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>>>Это же формальность? BFE>>Разумеется. И следование формальным правилам — ценное качество для программиста. E>Ценное качество для любого инженера, в том числе и программиста -- думать головой и понимать что зачем и почему именно так он делает... E>В данном случае имеет место быть размен — ошибки переполнения около нуля, против ошибок переполнения около бесконечности.
Для беззанаковых целых в С++ переполнения не бывает (в отличии от знаковых).
Если же говорить об ошибках допускаемых на крайних значениях, то их одинаково легко допустить для любого типа.
E>Ноль дрстижим всегда, а бесконечность, наоборот, удобно сделать недостижимой, правильно выбрав разрядность целых.
А если нужно писать одинаковый код для разных платформ? Я скорее предпочту выбрать соответствие диапазонов, чем разрядность.
BFE>>Ситуация редкая, но и память нынче дешевая. Что мешает написать: BFE>> v.reserv(N);// N — беззнаковое целое прочитанное из первого поля файла данных E>адресного пространства не хватит. Этомесли мы всё ещё о size_t...
Может, да. А может и хватить.
E>Мало того, Нормальная программа должна бы, прочитав N из файла, проверить его, как минимум на неотрицательность...
это беззнаковое-то число?
BFE>>особенно если учесть, что часто оставляют int тридцатидвухбитным даже на 64-битной архитектуре. E>Это ещё больше намекает нам, что даже 32-битный int на практике переполнить трудно.
Да, но ещё и потому, что "старый" код часто завязан на эту размерность.
E>но если таКой шанс есть, то надо брать не беззнаковую версию, а 64-битную!
И тут начинаются пляски с define'ами для подбора правильного int под размер данной платформы.