Re[3]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 12.11.06 20:17
Оценка: 21 (6) +8 -1 :)
Здравствуйте, Michael7, Вы писали:

А>>>С одной стороны вроде бы unsigned идеологически лучше.


АТ>>Лучше.


M>Чем? На мой взгляд существует очень ограниченный перечень случаев, когда unsigned оправдан, это флаги, коды значений, работа с памятью, может ещё пара случаев и всё. В принципе, ещё можно даже для арифметических операций, если не хватает диапазона значений знакового типа, но это уже грязный стиль и нежелательно.


Чем — это очень странный вопрос. Беззнаковые по своей природе сущности естественно представлять беззнаковыми типами. Тут, собственно, и вопросов никаких нет. Вопросы возникают именно тогда, когда кто-то начинает пытаться использовать знаковые типы для это цели. Вот тут действительно можно спросить, чем это вдруг оправданно такое странное использование знаковых типов. И в большинестве случаев оказывается, что знаковые типы просто-напросто чаще "прощают" беспечное отношение к коду. Во-первых, я считаю, что правильнее внимательнее относиться к коду, а не пытаться компенсировать лень использованием знаковых типов. Во-вторых, "безопасность" знаковых типов — не более чем иллюзия.

АТ>>Удобство unsigned как раз и состоит в частности в том, что их не надо проверять на отрицательные значения. Их надо проверять только на выход за верхний предел, если таковой существует (такая проверка, как правило, отловит и случайную передачу "отрицательного числа").


M>Сугубо моё мнение, но у меня сложилось впечатление, что потенциальные проблемы


Я не знаком ни с какими "потенциальными проблемами" беззнаковых типов. В моем коде, например, практически все целочисленные типы — беззнаковые, за исключением случаев, когда действительно приходится работать со знаковой величиной.

Вон в соседнем письме приведен пример, в котором использование беззнакового типа приводит к бесконечному циклу. Это пример, который показывает только то, что если писать беззнаковый код в манере знакового, то, разумеется, ничего хорошего их этого не получится. Делать из этого вывод о каких-то недостатках беззнаковых типов — это примерно то же самое, что пытаться писать Паскаль-код на языке С++, и, потерпев неудачу, заявлять, что это свидетельствует о недостатках языка С++.

M>перевешивают преимущества и применение unsigned делает код слегка менее прозрачным, а в некоторых случаях может создать проблемы при модификациях кода.


Я не вижу абсолютно никаких проблем с прозрачностью кода.

M>Например, казалось бы логично сделать индекс/счётчик беззнаковым, но в дальнейшем может оказаться, что проще всего присваивать ему отрицательные значения для обработки особых ситуаций.


А вот это — идеологически неправильно.

M>Дело в том, что использование беззнаковых типов в C/C++, вопреки ожиданиям, практически ничего не даёт в плане контроля за кодом на этапе компиляции, а только добавляет лишнюю сложность и ограничения.


Все эти "сложности и ограничения" — не более чем следствие применить порочные штампы мира знаковых типов к беззнаковым. Просто не надо пытаться это делать.

Также стоит упомянуть, что в С++ во многих контекстах выбор в пользу знаковых типов сдела на уровне языка и стандартной билиотеки. Сделан давно и навсегда. Это и 'size_t', и 'sid::vector<>:size_type' и т.п.

Еще стоит упомянуть, что те проблемы "с индексированием" (или с организацией счетчика цикла), который тут часто навязывают беззнаковым типам, на самом деле существуют в языках С/С++ с самого их рождения: например, в области адресной арифметики. Попробуйте организовать просмотр массива методом "скользящего указателя" в обратном направлении — и вам придется решать те же самые вопросы, которые возникают при обратной индексации массива беззнаковым индексом. Эти же вопросы приходится решать и при работе со стандартным итераторами. Так что говорить, что беззнаковые типы создают какие-то присущие именно им проблемы -совершенно неверно. Это не проблемы знаковых типов. Это соврешенно нормальная реальность программирования на С/С++ к которой рано или поздно все равно придется привыкать. А вот упоминающаяся тут манера безусловного использования знаковых типов — это не более чем попытка убежать от этой реальности.
Best regards,
Андрей Тарасевич
Re[4]: Нужен ли unsigned
От: remark Россия http://www.1024cores.net/
Дата: 13.11.06 21:11
Оценка: 24 (5) +4
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Беззнаковые по своей природе сущности естественно представлять беззнаковыми типами. Тут, собственно, и вопросов никаких нет.


Я всеми руками за типизацию. Если у переменной только два значения, то надо использовать bool, а не int. Если значение не меняется, то надо использовать const. Это замечательно, когда компилятор отлавливает ошибки. Это надо использовать всегда. Всегда, за исключением одного случая. Не надо использовать unsigned. Почему? Из-за реализации в языке. Проблема в том, что компилятор не отловит ошибки. Ну не отловит он и всё. И это получается ещё хуже, т.к. появляется чувство ложной уверенности. Думаешь, я завёл unsigned — всё, все мои проблемы решены. А на самом деле ничего не решено и компилятор практически ничего не контролирует.

Я могу, конечно, поприводить примеры типа таких:

    unsigned u = 0;
    int i = 0;
    u = i;
    i = u;
    // msvc80sp1 уровень предупреждений 4 — ни одного варнинга. Хотя оба из присваиваний могут вызвать проблемы...


    std::vector<int> v (3);
    for (size_t i = v.size() - 1; i >= 0; --i)
        std::cout << v[i];


Или вот ещё статья недавно проскакивала.

Но достаточно просто оценить какой шум вокруг этой темы вот уже на протяжении десятилетий. Десятилетиями программисты наступают на одни и те же грабли. Причём не самые плохие программисты (и вы предлагаете понаступать на них ещё немного всем нам). Почему? Они тоже надеются, что компилятор им чем-то поможет. Они тоже думают, что они повышают типизацию.

Фразы типа:

я считаю, что правильнее внимательнее относиться к коду, а не пытаться компенсировать лень использованием знаковых типов

Это из идеального мира. Действительно, давайте просто внимательно писать программы без ошибок.
В реальном мире, к сожалению, не так. Программисты работают по вечерам, по 12 часов, в спешке и т.д. Все мы писали и одинарное равно в if'е вместо двойного, и код типа примера выше и т.д. И очень бы хотелось, что бы при написании программ не надо было проявлять чудеса внимательности и памяти.

знаковые типы просто-напросто чаще "прощают" беспечное отношение к коду


Знаковые типы не просто прощают беспечное отношение к коду, они действительно заставляют больше кода работать корректно. Почувствуйте разницу. Посмотрите на цикл вверху. Что бы заставить его работать достаточно просто заменить size_t на int. Всё. Код будет корректным и рабочим.

Посмотрите пример в статья. Всё что достаточно сделать, что бы там код заработал. Правильно. Заменить unsigned на int.

Работу этого кода сломало единственное — замена signed на unsigned. Причём тоже из благих намерений. В цикле мы по каким индексам хотим пробежать? От size()-1 до 0. Может быть отрицательным? Нет. Заменяем signed на unsigned — код перестаёт работать!

В примере в статье процент в каком диапазоне может быть? От 0 до 100. Может быть отрицательным? Нет. Заменяем signed на unsigned — код (опять) перестаёт работать!

Я думаю таких примеров можно найти ещё.

Обратных же примеров, когда замена unsigned на signed ломает код, нет!
Если не считать, что у unsigned чуть больше диапазон. Но стоит ли оно того? Если уж надо хранить действительно большие числа, то имхо лучше воспользоваться int64_t. Тут и диапазон действительно больше, чем у int и проблем не будет.


Я недавно думал над этим вопросом. И изначально тоже отталкивался от точки, что всё должно быть максимально типизировано. И что надо использовать unsigned. Но потом после анализа таких примеров и кучи блогов, статей, постов по поводу ошибок связанных с unsigned, пришёл к указанному выводу — типизация везде, кроме unsigned. Ну не работает оно так как хочется. Не работает.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Нужен ли unsigned
От: Кодт Россия  
Дата: 13.11.06 09:35
Оценка: +7
Здравствуйте, Андрей Тарасевич, Вы писали:

<>
АТ>Я не знаком ни с какими "потенциальными проблемами" беззнаковых типов. В моем коде, например, практически все целочисленные типы — беззнаковые, за исключением случаев, когда действительно приходится работать со знаковой величиной.
<>

Не столько проблема, сколько неудобство (иногда).
В знаковой арифметике одно и то же неравенство можно выразить несколькими способами: x<y, x-y<0, 0<y-x, а в беззнаковой — единственным x<y. А если слева и справа — по нескольку слагаемых/вычитаемых, то рукодельная нормализация приводит к плохо читаемому коду.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[13]: Ответ другого оппонента :)
От: Андрей Тарасевич Беларусь  
Дата: 16.11.06 05:16
Оценка: 14 (2) :))) :)
Здравствуйте, Erop, Вы писали:

АТ>>(Другому оппоненту: а модульную арифметику, кстати, тоже придумали математики...)


E>ваша правда, товарищ эксперт, но таки когда математики думали о модульной арифметике, они как-то не ограничивали себя в выборе модуля между 0x100, 0x10000, 0x100000000 и 0x10000000000000000


Это еще что! Когда они думали об обычной арифметике, они также не ограничивали себя диапазоном -0x80000000..0x7FFFFFFF. И даже диапазоном 0x8000000000000000..0x7FFFFFFFFFFFFFFF не ограничивали! Я слышал историю про то, как в древности один мужик за изобретение какой-то игры (поддавки, кажется) затребовал 2^64-1 пшеничных зерна. И это было тогда, до инфляции...
Best regards,
Андрей Тарасевич
Re[15]: unsigned
От: Андрей Тарасевич Беларусь  
Дата: 15.11.06 19:22
Оценка: 55 (4) +1
Здравствуйте, Пётр Седов, Вы писали:

ПС>Здравствуйте, Erlond, Вы писали:


E>>Интересные аргументы приводятся "противниками" типа unsigned int.

ПС>Вряд ли здесь есть противники unsigned. Этот тип хорошо подходит для танцев с битами. Речь идёт об опасности беззнаковой арифметики.

Опасность — выдуманная.

E>>Количество — unsigned int, а разница — int.

ПС>Без приведений типа разница — тоже unsigned.

Значит надо не забывать делать приведение типа. Тут есть два очень важный момента, которые здесь уже упоминались.

Во-первых, приведение типа в данном случае — это не какой-то "странный каприз" спецификации языка, это преход между двумя приниципиально различными по своей природе арифметиками — обычной и модульной. Такой преход — событие настолько существенное, что делать его неявно в любом случае не стоит и, по этой причине, выполнение явного приведения типа более чем оправдано. Таких моментов в С/С++ навалом и избежать их не удастся отказом от безнаковых типов.

Во-вторых, в обычной арифметике в общем случае при вычитании двух N-битных чисел получается N+1-битное число. Это относится в одинаковой мере и к знаковым и к беззнаковым типам. То использование знаковых типов, которое пропагандируют тут противники беззнаковых, это в большинстве своем попытка закрыть глаза на существование этой проблемы на основании того, что работая рядом с "центром" диапазона знаковых чисел мы якобы находимся в болшей безопасности, чем работая рядом с "краем" беззнакового диапазона. Это ложная безопасность. С точки зрения достижения такой безопасности, всем следовало бы пользоваться самым большим знаковым типом ('long' или в C99 'long long') и это было бы самым "безопасным" и "защищенным от ошибок" вариантом. А все остальные типы объявим ненужными, предназначеннными для "экономии битов" в рамках разных (и, без сомнения, преждевременных) оптимизаций.

В реальности же закрывать глаза на проблему диапазона типа нельзя никогда, независимо от того знаков тип или беззнаков.

E>>И ещё меня, допустим, удивляет реализация CArray, где метод GetSize() возвращает int.

ПС>Это перестанет удивлять после дня, потраченного на поиск ошибки из-за беззнаковой арифметики.

Во-первых, я слышал аналогичные аргументы сторонников стиля 'if (5 == i)' — якобы запись 'if (i == 5)' приводит к ошибкам, которые потом надо будет искать днями. Реальность же показывает, что это не так.

В реальности я же лично чаще сталкиваюсь с тем, что программисты тратят дни на поиск ошибки, вызванной тем, что в функции сравнения кто-то решил сравнить два знаковых числа, путем вычитания одного из другого (и в один прекрасный день на одном из тестовых примеров вычитание перполнилось). Если бы программист, писавший это код, обладал хорошим опытом работы с беззнаковыми значениями, то он не допустил бы такой ошибки и при работе со знаковыми.

Интерсно, кстати, наблюдать, как оппоненты беззнаковых типов приводят тут примеры ошибок в их использовании, считая что эти примеры демонстрируют недостатки беззнаковых типов, в то время как на самом деле эти примеры демонстрируют одно из огромных практических преимуществ этих типов: ошибочный беззнаковый код как правило проявляет свою ошибочность сразу, практически на любом тестовом примере, в то время как ошибчный знаковый код зачастую проявляет свою ошибочность только на особо неудачном тестовом примере.

R>>>Но никакого "а типа вроде как количество товара не может быть отрицательным... заведу-ка я для него unsigned... ой а что это у меня получилось 4 миллиарда товаров?".

E>>А что, лучше когда у нас получается -5 единиц товара?
ПС>Конечно лучше. Ближайший assert обнаружит это:
ПС>
ПС>int Count;
ПС>...
ПС>assert(Count >= 0);
ПС>

ПС>В случае unsigned условие бессмысленно.

Разумеется, бессмысленно. Потому что не нужно.

E>>Почему странно получить 4 млрд, а -5 — нормально?

ПС>Это не нормально, это ошибка, но в случае int-а её можно обнаружить, а в случае unsigned — нет.

Неверно. Просто использован типичный для знакового программирования порочный "посметрный" способ обнаружения ошибки.
Best regards,
Андрей Тарасевич
Re[4]: Нужен ли unsigned
От: Michael7 Россия  
Дата: 13.11.06 21:11
Оценка: 7 (2) +3
Здравствуйте, Андрей Тарасевич, Вы писали:

M>>Чем? На мой взгляд существует очень ограниченный перечень случаев, когда unsigned оправдан, это флаги, коды значений, работа с памятью, может ещё пара случаев и всё. В принципе, ещё можно даже для арифметических операций, если не хватает диапазона значений знакового типа, но это уже грязный стиль и нежелательно.


АТ>Чем — это очень странный вопрос. Беззнаковые по своей природе сущности естественно представлять беззнаковыми типами. Тут, собственно, и вопросов никаких нет.


Пожалуй я с вами соглашусь где-то процентов так на 85
Но вопрос есть — что считать "беззнаковыми по своей природе сущностями"? На мой взгляд только те сущности, которым физически бессмыслено приписывать знак. Как-то: флаги, коды символов, безтиповое содержимое ячеек памяти (например при копировании откуда-то куда-то), указатели на память (их значение, а не тип на который они указывают). Наверное, ещё идентификаторы и хэши, хотя уже не уверен.

И, разумеется, это не догма. Если их применением достигается меньше ошибок и душевный комфорт программиста или например, вычисления получаются быстрее или компактнее код с беззнаковыми типами и это важно для программы, то применять надо беззнаковый тип.

Просто мой подход, что пока они не требуются их и не использовать.

АТ> И в большинестве случаев оказывается, что знаковые типы просто-напросто чаще "прощают" беспечное отношение к коду.


Что вы считаете в данном контексте безпечностью?

АТ> Во-первых, я считаю, что правильнее внимательнее относиться к коду, а не пытаться компенсировать лень использованием знаковых типов. Во-вторых, "безопасность" знаковых типов — не более чем иллюзия.


Понятно, что по-большому счёту безопасность кода не зависит от знаковости типа. Есть куча более серьёзных проблем. Полагаю Кернигана и Ритчи ещё не раз вспомнят "тихим незлым словом" за строки с нулём на конце от которых даже в C++ далеко не всегда удаётся уйти.

Просто мне кажется чуточку удобнее программировать со знаковыми типами, не переходя без нужды к беззнаковым. А раз удобнее, значит и чуточку более безопасно.

АТ>Делать из этого вывод о каких-то недостатках беззнаковых типов — это примерно то же самое, что пытаться писать Паскаль-код на языке С++, и, потерпев неудачу, заявлять, что это свидетельствует о недостатках языка С++.


Да нет недостатков у беззнаковых типов, как и у знаковых. А есть не всегда оправданное их применение, причём я думаю, что применять беззнаковые типы надо реже, чем это многими принято.

M>>Например, казалось бы логично сделать индекс/счётчик беззнаковым, но в дальнейшем может оказаться, что проще всего присваивать ему отрицательные значения для обработки особых ситуаций.


АТ>А вот это — идеологически неправильно.


Как сказать. Писал я как-то код для почти (были там некоторые извращения с перестановками и вставками) FIFO очереди , вполне ничего пошло принять отрицательный индекс начала для пустой очереди, а индекс хвоста в ноль с принудительным выставлением в (-1,0) после обработки последнего элемента. А отдельный признак заводить не хотелось.

AT> Так что говорить, что беззнаковые типы создают какие-то присущие именно им проблемы -совершенно неверно. Это не проблемы знаковых типов. Это соврешенно нормальная реальность программирования на С/С++ к которой рано или поздно все равно придется привыкать. А вот упоминающаяся тут манера безусловного использования знаковых типов — это не более чем попытка убежать от этой реальности.


Ещё раз повторю, что я не говорю о безусловном использовании, а скорее о приоритетном. То есть я воспринимаю беззнаковый тип как более сложный. Не в смысле структуры или реализации, где он как раз проще, а в смысле близости к человеческому восприятию.

P.S. Перечитал сообщение и стало где-то даже смешно, как бы не чересчур серьёзно мы обсуждаем довольно незначительные в общем-то аспекты программирования.
Re[2]: Нужен ли unsigned
От: Michael7 Россия  
Дата: 12.11.06 17:17
Оценка: 1 (1) +4
Здравствуйте, Андрей Тарасевич, Вы писали:

А>>С одной стороны вроде бы unsigned идеологически лучше.


АТ>Лучше.


Чем? На мой взгляд существует очень ограниченный перечень случаев, когда unsigned оправдан, это флаги, коды значений, работа с памятью, может ещё пара случаев и всё. В принципе, ещё можно даже для арифметических операций, если не хватает диапазона значений знакового типа, но это уже грязный стиль и нежелательно.

АТ>Удобство unsigned как раз и состоит в частности в том, что их не надо проверять на отрицательные значения. Их надо проверять только на выход за верхний предел, если таковой существует (такая проверка, как правило, отловит и случайную передачу "отрицательного числа").


Сугубо моё мнение, но у меня сложилось впечатление, что потенциальные проблемы перевешивают преимущества и применение unsigned делает код слегка менее прозрачным, а в некоторых случаях может создать проблемы при модификациях кода. Например, казалось бы логично сделать индекс/счётчик беззнаковым, но в дальнейшем может оказаться, что проще всего присваивать ему отрицательные значения для обработки особых ситуаций.

Дело в том, что использование беззнаковых типов в C/C++, вопреки ожиданиям, практически ничего не даёт в плане контроля за кодом на этапе компиляции, а только добавляет лишнюю сложность и ограничения.
Re[3]: Где тут ошибка
От: Erop Россия  
Дата: 13.11.06 15:37
Оценка: 1 (1) +1 -3
Здравствуйте, Шахтер, Вы писали:

Ш>
Ш>void func(char *p,size_t s)
Ш> {
Ш>  for(int i=0; i<s ;i++) p[i]=0;
Ш> }
Ш>


Ш>Надо обьяснять, где здесь ошибка?


Зачем объяснять?
Ошибка в том, что s имеет беззнаковый тип.
Она же допущена и в std::vector

Ну и что?

1) реально size таким большим не бывает, так как в память плохо помещается
2) Лично я и std::vector не пользуюсь. Пользуюсь массивами из другой библиотеки, там размер массива int
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: C++ For Secretary
От: remark Россия http://www.1024cores.net/
Дата: 16.11.06 18:49
Оценка: 1 (1) -1 :)))
Здравствуйте, Erop, Вы писали:

E>или это он всё писал для секретарш иногда применяющих С++ для своих нужд





1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Всё очень просто....
От: Erop Россия  
Дата: 12.11.06 13:58
Оценка: +2 -3
Здравствуйте, Аноним, Вы писали:

А>Что вы думаете по этому поводу?


signed -- для чисел
unsigned -- для флажков.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Безумью храбрых...
От: Erop Россия  
Дата: 17.11.06 13:02
Оценка: +2 :)))
Здравствуйте, Vain, Вы писали:

V>
V>#ifdef _DEBUG
V>typedef int MYLIB_SIZE;
V>#else
V>typedef unsigned int MYLIB_SIZE;
V>#endif
V>



Прекрасный, надёжный способ сделать неотлаживаемую программу, которая в релизе и дебаге гарантированно ведёт себя по-разному!!!

Не поделишься зачем это надо?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Нужен ли unsigned
От: Аноним  
Дата: 17.11.06 04:50
Оценка: 21 (2) +2
M>>Чем? На мой взгляд существует очень ограниченный перечень случаев, когда unsigned оправдан, это флаги, коды значений, работа с памятью, может ещё пара случаев и всё. В принципе, ещё можно даже для арифметических операций, если не хватает диапазона значений знакового типа, но это уже грязный стиль и нежелательно.
Полностью поддерживаю.

АТ>Чем — это очень странный вопрос. Беззнаковые по своей природе сущности естественно представлять беззнаковыми типами. Тут, собственно, и вопросов никаких нет.

То есть ты используешь unsigned чтобы подчеркнуть что переменная не может содержать отрицательные значения?

Или чтобы выгадать еще один бит? Или и то и то?

Если чтобы подчеркнуть что переменная не может содержать отрицательные значения, то, имхо, само название переменной должно отражать неотрицательность чисел (а не ее тип).

АТ>Вопросы возникают именно тогда, когда кто-то начинает пытаться использовать знаковые типы для это цели. Вот тут действительно можно спросить, чем это вдруг оправданно такое странное использование знаковых типов.

Эээ... Наоборот, вопрос возникнет по какой такой причине программист использовал unsigned вместо signed. За желание выгадать еще один бит — нужно отрывать руки.

При signed мы всегда знаем является ли число отрицательным, нулем или положительным. При unsigned такой гарантии нет; мы не знаем является ли unsigned число большим положительным или какое-то отрицательное число было сохранено в беззнаковой переменой. То есть в случае с беззнаковыми переменными происходит потеря информации, а именно знак числа.

АТ>И в большинестве случаев оказывается, что знаковые типы просто-напросто чаще "прощают" беспечное отношение к коду.

В знаковых типах просто не происходит потери информации, и это уже дает кое-какие гарантии и вовсе не свидетельствует о беспечном отношении к коду. Наоборот, желание делать все как "правильно" (хранить неотрицательные сущности в беззнаковых переменных) может повредить.

АТ>Во-первых, я считаю, что правильнее внимательнее относиться к коду, а не пытаться компенсировать лень использованием знаковых типов. Во-вторых, "безопасность" знаковых типов — не более чем иллюзия.

Ты серьезно считаешь что программистам лениво написать unsigned для всех неотрицательных сущностей? Респект!

На счет более внимательного отношения к коду — согласен. Только внимательность должна проявляться не в делании типа беззнаковым, а брать тип (не обязательно integral) с большим числом битов если их не хватает.

АТ>>>Удобство unsigned как раз и состоит в частности в том, что их не надо проверять на отрицательные значения. Их надо проверять только на выход за верхний предел, если таковой существует (такая проверка, как правило, отловит и случайную передачу "отрицательного числа").

Аргумент что для беззнаковых чисел нужно только делать одну проверку на принадлежность значения какому-то домейну не катит ибо можно передать, к примеру, в функцию (у которой один беззнаковый параметер) по ошибке какое-то отрицательное число которое тем не менее может быть сконвертировано в большое положительное число находящееся в диапазоне правильных чисел.

Или представь такую простую задачу. Ты получаешь площади квадратов, очень большие положительные числа. Согласно твоей логике, и стороны квадрата и сама площадь не могут быть отрицательными — поэтому ты их делаешь unsigned. Тебе надо найти их сторону. Для этого ты, скорее всего, воспользуешся стандартной функцией которая принимает double. И теперь вопрос, положительное или отрицательное число окажется в самой функции? Мой ответ — я не знаю но я твердо знаю что если signed будет конвертированно в double, то знак останется.

M>>Сугубо моё мнение, но у меня сложилось впечатление, что потенциальные проблемы

У меня также ибо происходит потеря информации — знак числа.

АТ>Я не знаком ни с какими "потенциальными проблемами" беззнаковых типов. В моем коде, например, практически все целочисленные типы — беззнаковые, за исключением случаев, когда действительно приходится работать со знаковой величиной.

Я выше уже сказал главную проблему беззнаковых типов — потеря информации.

M>>перевешивают преимущества и применение unsigned делает код слегка менее прозрачным, а в некоторых случаях может создать проблемы при модификациях кода.


АТ> Я не вижу абсолютно никаких проблем с прозрачностью кода.


M>>Например, казалось бы логично сделать индекс/счётчик беззнаковым, но в дальнейшем может оказаться, что проще всего присваивать ему отрицательные значения для обработки особых ситуаций.


АТ>А вот это — идеологически неправильно.

Это еще почему? Например, делаем линейный поиск в массиве. Не нашли элемент, вернули -1. Можно, конечно, вернуть индекс сразу за концом массива, но если следовать такой логике, то NULL тоже возвращаться из функций при работе с указателями нельзя.

АТ>Также стоит упомянуть, что в С++ во многих контекстах выбор в пользу знаковых типов сдела на уровне языка и стандартной билиотеки. Сделан давно и навсегда. Это и 'size_t', и 'sid::vector<>:size_type' и т.п.

Это не аргумент. Там тоже люди, и они могли не представлять к каким последствиям это может привести. Сдается мне что беззнаковые типы они выбрали по причине что неотрицательные числа "должны" представляться беззнаковыми числами (то что ты и говоришь) а не чтобы выгадать один бит. И тем не менее сам Бьярн использует int в циклах, к примеру, хотя если уж следовать стандарту, то он должен был бы писать unsigned.
Re[3]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 13.11.06 20:22
Оценка: 4 (2) +2
Здравствуйте, Michael7, Вы писали:


Ш>>1) Беззнаковая арифметика имеет точно определённую семантику, в отличии от знаковой.


M>Вы не могли бы пояснить, потому что мне представляется, что это архитектурно зависимо.


Нет. Какая-то свобода представления значений целых чисел в С/С++ имеется только для знаковых типов. Для беззнаковых все жестко. (Кроме диапазонов, разумеется).

Ш>>2) В беззнаковой арифметике лего ловить переполнение.


Ш>>
Ш>>unsigned a=...;   
Ш>>unsigned b=...;

Ш>>a+=b;

Ш>>if( a<b ) 
Ш>>  { //overflow  
Ш>>   ... 
Ш>>  }
Ш>>


M>Код изящен и эффективен, но думаю может привести к неприятным трудноуловимым ошибкам. В стандарте C99 результат целочисленного переполнения UB, как в C++2003 стандарте менее ясно, там как-то закручено по-моему.


Результат знакового целочисленного переполнения — UB. Беззнаковые типы реализуют арифметику по модулю, т.е. у них не бывает "переполнения" или, другими словами, традиционное переполнение у них приводит к однозначно оговоренному эффекту без какого-либо UB.

M>По-моему, очевидно и то, что результат может зависеть как от архитектуры компьютера, так и даже от компилятора и остального кода.

M>Даже в случае x86 процессора после переполнения выставляется флаг C (carry flag) и нет никакой уверенности в том, как он используется остальным сгенерированным кодом.

Нет. Уверенность есть. На уровне языка. Если "остальной код" начинает как-то неадекватно реагировать на CF в этом случае, или это начинает зависеть от архитектуры, или от компилятора, то все это — глюки компилятора. Но речь не об этом.
Best regards,
Андрей Тарасевич
Re[12]: Таки проще! :)
От: Erop Россия  
Дата: 14.11.06 11:59
Оценка: 3 (1) +1 -2
Здравствуйте, Roman Odaisky, Вы писали:

RO>Желающие могут попробовать:

RO>
RO>var a: array[-1..1] of whatever;
RO>. . .
RO>a[-2] = 0;
RO>

RO>много счастья будет?
<... много пропустил ...>

RO>с итераторами это хоть и можно, но сложнее, придется какой-то свой skip_iterator соображать.


Собственно мы примерно до одного договрились.
Отличия:

1) В примере с паскалем индекс можно выводить из диапазона [-1..1]. Нельзя по неверному индексу лазить в массив. но это нельзя при любом раскладе что знаковый индекс, что беззнаковый

2) Про доступ к элементу массива с индексом -1 в С++. Та же ровно песня. А итерация массива при помощи указателя -- ИМХО нечитабельно и ненадёжно. И не только потому, что можно за границу сегмента вылететь (на практике это таки трудно часто, так как перед массивами обычно ещё что-нибудь служебное кладут). Короче неудобно это. Люди так не думают. Лучше пусть все занимаются своим делом.
Люди пишут доступ к массивам через индексы, оптимизаторы, если хотят и могут, компилируют это в код, работающий с указателями, а программист оставляет голые указатели для хаккеров и страшных снов

3) Как быть без итераторов?
Собственно я вот отказался от использования STL и его представления об итераторах и не жалею нисколько. И как-то пока ни разу не хотелось вернуться
Я даже не против идеи итератора как такового. Только итераторы надо рожать там, где они действительно нужны, а не всюду и всегда ?)
Просто мне кажется, что для доступа к массиву намного удобнее индекс
А вообще итератор чего-то, как идея, не всегда плох. Хотя то, что ты назвал енумератором, обычно проще в реализации и не сложнее в использовании
Мне особенно не нравятся итераторы из STL потому что они копируют зачем-то семантику указателей.
Вроде как все попробовали и осознали, что писать на голых указателях стрёмно. и не только потому, что не безопасно, но и потому, что непонятно
На кой нарожали три мешка шаблонов, чтобы доступ к довольно высокоуровневым коллекциям, загнуть в такую же уродскую парадигму -- я лисно понять совершенно не могу
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 12.11.06 16:40
Оценка: 1 (1) +2 :)
Здравствуйте, Аноним, Вы писали:

А>Но как меня всякие мелочи задолбали, извините. Чуть чуть перепутал, и всё, 4 миллиарда, вся логика валится.

А>Если int-ы хоть можно проверить на -1, то unsigned-ы как проверишь? Непонятно.

Не совсем понятно, причем здесь именно -1.

Также непонятно, откуда взялись эти 4 миллиарда. Такое могло призойти, например, если где-то в программе перемешиваются знаковые и беззнаковые типы или если где-то из меньшего вычитается большее. В первом случае (если мешать signed и unsigned действительно необходимо) надо было проверять на отрицательные значеня непосредственно перед переходом от signed к unsigned. Во втором случае надо было проверять на вычитание большего из меньшего.

А>Собственно вопрос, оправдан ли такой геморрой? Или сделать :%s/unsigned/int/g и жить счастливой жизнью?


Нет там никакого геммороя. В том виде, в котором все это описано в твоем сообщении, это звучит как "беззнаковые типы не дают мне сделать ошибку и я не могу проверить ее наличие"

А>С одной стороны вроде бы unsigned идеологически лучше.


Лучше.

А>Но с другой, не получается у меня нормально с ними писать. Каждый раз, когда фунцию с аргументом типа unsigned вызываешь, надо проверять, не передастся ли туда отрицательное число, а если бы она была int, то проверку можно было бы сделать внутри функции


Удобство unsigned как раз и состоит в частности в том, что их не надо проверять на отрицательные значения. Их надо проверять только на выход за верхний предел, если таковой существует (такая проверка, как правило, отловит и случайную передачу "отрицательного числа"). А если верзхнего предела не существует в принципе — то и проверять ничего не надо.

Откуда возникает проблема "не передастся ли туда отрицательное число" — мне не понятно, ибо не понятно откуда может даже возникнуть возможность передать отрицательное число — то, что передается, тоже должно быть unsigned. Если же в этом месте происходит необходимый переход от signed к unsigned значениям (что бывает нечасто), то проверка, разумеется, делается в момент перехода, т.е. снаружи функции.
Best regards,
Андрей Тарасевич
Re[7]: Где тут ошибка
От: Erop Россия  
Дата: 14.11.06 16:34
Оценка: 1 (1) +1 -1 :)
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Необходимость "что-то вычитать" никак не служит аргументом в пользу знакового типа. Из беззнакового типа тоже можно "что-то вычитать". Если в предметной области допустимы только положительные значения, то получиение отрицательного значения в знаковом типе ничем принципиально не отличается от получения черезменрно большого значения в беззнаковом. Разница только в том, что, как тут уже говорилось, со знаковым типом придется ловить обе ситуации (выход за пределы вниз и вверх), а с беззнаковым только одну. Это, как раз таки, аргумент в пользу беззнакового типа.



Нет уж. Числа лучше бы использовать нормальные.
И отлаживать проще и программировать и всё такое.

Это примерно так же, как если величина принимает толкьо чётные значения, то надо хранить от неё половину
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Нужен ли unsigned
От: Vain Россия google.ru
Дата: 16.11.06 17:56
Оценка: 1 (1) -2 :)
Здравствуйте, Аноним, Вы писали:

Решил добавить от себя немного.
Когда мне надо использовать с одной стороны беззнаковай инт как самый близкий для хранения неотрицательных значений (к примеру, размер массива), с другой, знаковай для проверки на выход за диапазон (assert(m_nSize>=0)), — использую такой тип:
#ifdef _DEBUG
typedef int MYLIB_SIZE;
#else
typedef unsigned int MYLIB_SIZE;
#endif

void foo(MYLIB_SIZE size) {
  assert(size >= 0);
}
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[5]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 12.11.06 20:30
Оценка: +3 -1
Здравствуйте, Michael7, Вы писали:

M>Здравствуйте, Андрей Тарасевич, Вы писали:


AL>>>
AL>>>unsigned someCounter = 99;
AL>>>while(--someCounter >= 0)
AL>>>{
AL>>>  //ooops! infinite loop here
AL>>>} 
AL>>>


АТ>>И? Неправильно реализованный цикл работает, разумеется, неправильно. И что из этого?


M>Очень хороший пример.


M>Применение unsigned излишне нагружает программисту мозг, заставляя его лишнего следить за кодом, в то время как казалось бы он мог рассчитывать отдохнуть на более строгом контроле типов.


Нет. Применение unsigned учит программиста специфике программирования в ситуации, когда существует реальная опасность выхода за границы интервала. С точно такой же по своей сути проблемой программист столкнется и в таком случае

int a[N];
int* p = a + N;

while (--p >= a)
  *p = 0;


Типичный 'int'-овый программист зачатсую даже и не видит проблемы в этом коде. Более того, такой код зачастую "работает". В то время как на самом деле этот код приводит к неопределенному поведению и его поведение предсказать трудно. Он запросто может привести и к бесконечному циклу. Решить проблему в данном случае беспечным переходом к какому то "знаковому" типу не удастся. Наду учиться жить в "беззнаковом" мире.

Правильная реализация такого цикла

int a[N];
int* p = a + N;

while (p > a)
  *--p = 0;


является одним из варинатов "шаблонного" решения, применимого и к примеру с unsigned циклом

unsigned someCounter = 99;
while(someCounter > 0) {
  --someCounter
  ...
}


хотя для случая арифметического типа можно поступить и так

unsigned someCounter = 99;
while(someCounter-- > 0) {
  ...
}


Я могу лишь посторить, что специфика "близости края интервала", присущая беззнаковым типам и за которую их часто "не любят", в языках С и С++ присуща далеко не только беззнаковым типам. Если внимательно поискать, найти ее можно практически везде. И спрятаться от нее вам не удастся, как бы вы этого не хотели.
Best regards,
Андрей Тарасевич
Re[5]: Всё очень просто....
От: Аноним  
Дата: 17.11.06 05:03
Оценка: 9 (1) +1 :)
E>>>>signed -- для чисел
E>>>>unsigned -- для флажков.
Ш>>>По-моему, это та простота, которая хуже воровства.

E>>Ну прости, я ответил на вопрос, что же я таки думаю.

E>>ИМХО выгоды от использования беззанковых чисел всегда какие-то призрачные.

Ш>Речь идет не а выгодах. Речь идет о том, зачем вообще нужна беззнаковая арифметика (см. заглавную тему).

Ш>Она нужна для решения огромного количества задач.

Ш>Например, напиши struct IPHeader без беззнаковых типов. Или сделай алгоритм вычисления CRC (а так же SHA, DES, длинная арифметика и.т.п.).

То есть ты прибавляешь один IP к другому, а порты отнимаешь друг от друга и две получившиеся величины перемножаешь между собой?
Re: Нужен ли unsigned
От: Шахтер Интернет  
Дата: 13.11.06 10:29
Оценка: 6 (1) +2
Здравствуйте, Аноним, Вы писали:

А>Что вы думаете по этому поводу?


В моём коде чаще всего используются беззнаковые переменные, чем знаковые.
Причин тут несколько.

1) Беззнаковая арифметика имеет точно определённую семантику, в отличии от знаковой.

2) В беззнаковой арифметике лего ловить переполнение.

unsigned a=...;   
unsigned b=...;

a+=b;

if( a<b ) 
  { //overflow  
   ... 
  }


3) В C/C++ размерности массивов выражаются беззнаковым типом size_t. По этой причине ипользовать для индексирования знаковые типы -- создавать потенциальные дыры.

4) LUT удобнее делать с беззнаковыми типами. Классический пример.

bool CharIsXXX(char c)
 {
  static const bool table[256]={...};

  return table[(unsigned char)c];
 }
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[10]: Не! проще таки лучше!
От: Erop Россия  
Дата: 14.11.06 09:26
Оценка: 3 (1) +1 -1
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Во-первых, в STL — это необходимость реализации именно абстракций. Поэтому стали пользоваться новыми добрыми простыми и надёжными способами. И они, похоже, даже добрее, проще и недежней. Что делает осмысленным из использование и за пределами STL.


АТ>Во-вторых, к STL все это отностся на самом деле мало. Эти "абстакции" зарыты намного глубже.


АТ>(Причины приведения примеров не совсем понятны).


Плохо, что не понятны.
Я предалагаю STL подробно не обсуждать. просто, АФАИК идеи о unsigned индексах и размерах массивов появились вместе с изобретением STL.

Ну а с тем, что "эти абстракции" зарыты намного глубже я тоже совершенно согласен.
про то и вопрос. От чего в языке фортран или там паскаль массивы было удобно итерировать знаковым индексом, а в C++ + STL стало так трудно и опасно?


Да, от чего вообще в этом обсуждении возник STL.
Собственно ты сам начал проводить аналогии между unsigned индексом и STL-ными итераторами.
Действительно и там и там нельзя сделать "лишний шаг"
А в знаковом индексе -- можно.

После этого ты стал утверждать, что раз уж в STL-way (через указатели и итераторы) итерации лишний шаг делать нельзя, то не надо приучаться к такой возможности при итерации через индекс.

А я во делаю совершенно противоположенный вывод. Раз уж в STL-way делать "лишний шаг" опасно, а часто хочется, то это косяк STL-way.
Возможно у этого пути естьи плюсы, но конкретно это -- минус. Косяк, провоцирующий ошибки. Для того, чтобы избежать их, предлагается писать все итерации массивов через unsigned индекс. Мне кажется, что лучше избегать STL-way итерации.

Забавно, кстати, что сами авторы STL пожоже это тоже чувствовали. Потому что понаписали всяких for_each
В принципе я их понимаю. Так как простой for() при использовании итераторов и unsigned индексов действительно становится неудобным и опасным
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[16]: unsigned
От: remark Россия http://www.1024cores.net/
Дата: 17.11.06 19:45
Оценка: 2 (2) +1
Здравствуйте, Андрей Тарасевич, Вы писали:

Похоже разговор начинает заходить в бесконечную рекурсию


АТ>Значит надо не забывать делать приведение типа. Тут есть два очень важный момента, которые здесь уже упоминались.


АТ>Во-первых, приведение типа в данном случае — это не какой-то "странный каприз" спецификации языка, это преход между двумя приниципиально различными по своей природе арифметиками — обычной и модульной. Такой преход — событие настолько существенное, что делать его неявно в любом случае не стоит и, по этой причине, выполнение явного приведения типа более чем оправдано. Таких моментов в С/С++ навалом и избежать их не удастся отказом от безнаковых типов.


Вот именно, что переход между знаковой и беззнаковой арифметикой — событие существенное. Сразу возникает следующий вопрос. Коли уж нам не избежать делания этого перехода постоянно, т.к. "количество товара" — беззнаковое, а "разница между количествами товара" — знаковое, ЗАЧЕМ НАМ УСЛОЖНЯТЬ СЕБЕ ЖИЗНЬ ЭТИМИ ПОСТОЯННЫМИ ПЕРЕХОДАМИ? Которые (по твоим же словам) вещь серьёзная и требующая постоянного внимания и дополнительного кода. В конце концов нам никто не запрещает в int хранить положительные числа.

Был бы очень признателен за конкретный ответ на этот конкретный вопрос.

Сразу хотел бы ответить на 2 возможных ответа (не знаю, ответил бы ты ими или нет, неважно)
1. Беззнаковое увеличивает нам диапазон в 2 раза.
Ну и что? Если уж число действительно такое большое, что речь идёт о переполнении значения вверх, то это нам не даст ровным счётом ничего. Лишь небольшая затычка.
2. Использование беззнакого спасёт от каких-то ошибок.
Каким образом? Если уж мы будем делать проверки на переполнения перед каждым выполнением арифметического действия (очень сомнительно в реальной жизни, если используются голые примитивные типы), то тут без разницы используем мы знаковое или нет. Если мы таких проверок не делаем, то беззнаковое только ухудшит ситуацию, т.к. после выполнения какого-то длинного вычисления, мы хотя бы имеем возможность проверить, что у нас получилось отрицательное "количество" и вызвать ассёрт/исключение и т.д.


АТ>Во-вторых, в обычной арифметике в общем случае при вычитании двух N-битных чисел получается N+1-битное число. Это относится в одинаковой мере и к знаковым и к беззнаковым типам. То использование знаковых типов, которое пропагандируют тут противники беззнаковых, это в большинстве своем попытка закрыть глаза на существование этой проблемы на основании того, что работая рядом с "центром" диапазона знаковых чисел мы якобы находимся в болшей безопасности, чем работая рядом с "краем" беззнакового диапазона. Это ложная безопасность. С точки зрения достижения такой безопасности, всем следовало бы пользоваться самым большим знаковым типом ('long' или в C99 'long long') и это было бы самым "безопасным" и "защищенным от ошибок" вариантом. А все остальные типы объявим ненужными, предназначеннными для "экономии битов" в рамках разных (и, без сомнения, преждевременных) оптимизаций.


АТ>В реальности же закрывать глаза на проблему диапазона типа нельзя никогда, независимо от того знаков тип или беззнаков.


Ну не знаю.
А если речь идёт о количестве строк, введённых пользователем, или количестве водителей в полисе ОСАГО и т.д.
Нет, строго говоря, тут тоже надо проверять на переполнение за 2 млрд.
И я даже думаю, что если ты повводишь в разные программы по 5 млрд чего-либо, то ты "уронишь" много программ... но я, честно говоря, не особо виню авторов этих программ.

Ну и опять же, как ты сам сказал, что это не имеет никакого отношения к signed/unsigned.


АТ>Интерсно, кстати, наблюдать, как оппоненты беззнаковых типов приводят тут примеры ошибок в их использовании, считая что эти примеры демонстрируют недостатки беззнаковых типов


Да, нет же... ну я по крайней мере... не недостатки беззнаковых типов! А то, что при использовании их писать сложнее, надо проявлять больше внимания и т.д. Ну вот ты сам написал вверху, что переходы между арфиметиками дело серьёзное, требующее внимания. Или вот тут неоднократно приводили примеры, что сравнения чего-либо можно легко и правильно и логично записать с помощью знаковых типов и можно сложно, внимательно, с дополнительными проверками записать с помощью знаковых.

Очень хотелось бы услышать твой ответ именно с этой стороны.




АТ>, в то время как на самом деле эти примеры демонстрируют одно из огромных практических преимуществ этих типов: ошибочный беззнаковый код как правило проявляет свою ошибочность сразу, практически на любом тестовом примере, в то время как ошибчный знаковый код зачастую проявляет свою ошибочность только на особо неудачном тестовом примере.


Ты упустил ещё третью часть. Есть код, который будучи записанным со знаковыми числами работает, т.е. в нём и нет ошибок и не надо их искать, а будучи записанным с беззнаковыми числами становится с ошибками и их действительно надо искать. Например, примеры со сравнениями и вычитаниями, которые тут приводились неоднократно.



E>>>Почему странно получить 4 млрд, а -5 — нормально?

ПС>>Это не нормально, это ошибка, но в случае int-а её можно обнаружить, а в случае unsigned — нет.

АТ>Неверно. Просто использован типичный для знакового программирования порочный "посметрный" способ обнаружения ошибки.


Что за посмертный метод обнаружения? А при использовании беззнаковых чисел, если ты обнаруживаешь что будет переполнение, какие варианты? Есть какой-то «непосмертный» способ обнаружения/реакции на это?

Ну разьве не приятно написать:

void f(int i)
{
  assert(i > 0);
  // ...
}


Вместо:

// во всех 100 местах, где вызывается f()
assert(x > y)
f(x - y);



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Нужен ли unsigned
От: A.Lokotkov Россия http://www.linkedin.com/pub/alexander-lokotkov/a/701/625
Дата: 12.11.06 19:40
Оценка: 1 (1) :))
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Не совсем понятно, причем здесь именно -1.

АТ>Также непонятно, откуда взялись эти 4 миллиарда.
unsigned someCounter = 99;
while(--someCounter >= 0)
{
  //ooops! infinite loop here
}
bloß it hudla
Re[3]: А может пусть лучше оптимизатор сокращает?
От: Андрей Тарасевич Беларусь  
Дата: 13.11.06 18:14
Оценка: 1 (1) +1 :)
Здравствуйте, Erop, Вы писали:

Конечно, лучше! Вот только где бы найти такой оптимизатор... Т.е. ясно, что нет такого оптимизатора и быть не может, но все равно — лучше бы он...
Best regards,
Андрей Тарасевич
Re[8]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 18:13
Оценка: 1 (1) :))
Здравствуйте, Erop, Вы писали:

АТ>>Неверно. 'atoi' и иже с ними — функции "мертвые" и практической ценности не представляющие.

E>А почему?

Интересно видеть, как пользователь Erop помечает сообщение через "выразить несогласие" и при этом одновременно задает вопрос "Почему?". На каком же основании Вы, уважаемый Erop, выражаете свое несогласие, не понимая при этом, о чем идет речь?
Best regards,
Андрей Тарасевич
Re: Нужен ли unsigned
От: Michael7 Россия  
Дата: 12.11.06 13:37
Оценка: +3
Здравствуйте, Аноним, Вы писали:

А>Я решил попробовать писать "правильный" код. Для ширины например — unsigned, т.е. она не бывает


А я наоборот, полагаю, что unsigned, по возможности, надо объявлять только в редких случаях и только для неарифметических по смыслу переменных. То есть таких, над которыми никогда не проводятся арифметические операции. И даже для них, если нет нужды не надо unsigned, так я почти никогда не объявляю unsigned даже индексные переменные. Иначе чревато трудно обнаружимыми ошибками в промежуточных вычислениях.
Re[6]: Нужен ли unsigned
От: johny5 Новая Зеландия
Дата: 13.11.06 09:26
Оценка: :)))
АТ>
АТ>int a[N];
АТ>int* p = a + N;

АТ>while (--p >= a)
АТ>  *p = 0;
АТ>


АТ>Типичный 'int'-овый программист зачатсую даже и не видит проблемы в этом коде. Более того, такой код зачастую "работает". В то время как на самом


Что то я действительно не вижу проблем в таком коде...
Re[6]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 06:23
Оценка: +1 -1 :)
Здравствуйте, Nuzhny, Вы писали:

N>Добавлю ещё чуть-чуть: нет функций преобразования С-строк к unsigned типам. Есть atoi, atol, atoi64. И ни одного unsigned.


Неверно. 'atoi' и иже с ними — функции "мертвые" и практической ценности не представляющие. Немножко "живее" — 'sscanf', который поддерживает unsigned, но и тот, к сожалению, неполноценен. Настоящие функции преобразования строк к целым из библиотеки С — 'strtol' и 'strtoul' (плюс 'll' версии в С99), из которых последняя как раз unsigned.
Best regards,
Андрей Тарасевич
Re[6]: Нужен ли unsigned
От: remark Россия http://www.1024cores.net/
Дата: 14.11.06 15:46
Оценка: +1 -1 :)
Здравствуйте, Шахтер, Вы писали:

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


R>>Здравствуйте, Андрей Тарасевич, Вы писали:


АТ>>>Беззнаковые по своей природе сущности естественно представлять беззнаковыми типами. Тут, собственно, и вопросов никаких нет.


R>>Я всеми руками за типизацию.


Ш>Типизация здесь не причем. Вообще.


Можно называть подбор подходящего типа для хранения величины как угодно. Суть от этого не изменится.



Ш>Этот шум не стоит выеденного яйца. Беззнаковые типы широко используются в программировании и будут использоваться, поскольку без них многие задачи вообще не решаются. Так что нужно не шуметь, а просто выучить беззнаковую арифметику и научится грамотно её использовать -- там где она необходима.

Ш>Ну и кстати, понимание того, где какую арифметику нужно использовать тоже приходит со знаниями и опытом.

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


Ш>Это невозможно. Память, внимательность и хорошее понимание как нужно решать задачу -- это основа успешной работы программиста.


Да. Только для одного кода их почему-то надо значительно больше чем для другого.
В одном коде почему-то приходится напрягаться до максимума, что бы уследить и удержать в памяти все тонкие моменты (и не дай бог к тебе кто-нибудь подойдёт с глупым вопросом в этот момент), а в другом коде как-то без особых напрягов получается разбираться и модифицировать.


R>>

R>>знаковые типы просто-напросто чаще "прощают" беспечное отношение к коду


R>>Знаковые типы не просто прощают беспечное отношение к коду, они действительно заставляют больше кода работать корректно. Почувствуйте разницу. Посмотрите на цикл вверху. Что бы заставить его работать достаточно просто заменить size_t на int. Всё. Код будет корректным и рабочим.


Ш>Нет, не будет. v.size()-1 не обязательно представимо положительным int. Фокус не удался.


Если уж на то пошло, то ты уверен, что для любого контейнера размер представим и unsigned? Фокус тоже не удался. Ну заменили int на unsigned и что? Ну в два раза увеличился диапазон.
Ну если уж вернуться на землю, то я думаю, что не сильно ошибусь, если скажу, что для 99% всех используемых контейнеров int'a хватит.


Ш>
Ш>    std::vector<int> v (3);
Ш>    for (size_t i = v.size() - 1; i!=size_t(-1) ; --i)
Ш>        std::cout << v[i];
Ш>


Ш>Можно сделать вот так.


Ш>
Ш>    std::vector<int> v (3);
Ш>    for (size_t i = v.size() ; i-- ;)
Ш>        std::cout << v[i];
Ш>


Ш>Но лучше вот так.


Ну тут можно до бесконечности соревноваться в мастерстве... а можно просто написать код и он будет работать.


Ш>Примеров откровенного ламерства, когда люди простейший цикл не могут написать, действительно можно найти вагон и прицепную тележку.


Да, да. Уволим уже наконец всех этих ламеров!


R>>Обратных же примеров, когда замена unsigned на signed ломает код, нет!


Ш>Постановка вопроса некорректна. Это примерно тоже самое, что экспериментирвать, что будет если в топливный бак вместо саляры залить бензин или наоборот.

Ш>Сломается японская пила или нет?

Почему?


R>>


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[9]: Нужен ли unsigned
От: Шахтер Интернет  
Дата: 15.11.06 09:12
Оценка: -1 :))
Здравствуйте, Кодт, Вы писали:

Я бы сделал вот так.

class Line
 {
   int a,b; // [a,b] a<=b

  public:

   Line(int a_,int b_) { if( a_<=b_ ) a=a_,b=b_; else a=b_,b=a_; }

   // Нормализация хороша ещё и тем, что облегчает реализацию других операций с отрезком

   unsigned length() const { return unsigned(b)-unsigned(a); }
 };


int a,b,c,d;

Line(a,b).length() < Line(c,d).length()


По моему этот пример демонстрирует не мощь знаковой арифметики, а плохой стиль программирования на рассыпухе.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[15]: Ответ другого оппонента :)
От: Аноним  
Дата: 16.11.06 12:07
Оценка: +3
Сдается мне, что Андрей прекрасно знает эту сказку и его слова про "некоего мужика", который "изобрел поддавки" — это типа шутка
Re[2]: Предложение
От: Андрей Тарасевич Беларусь  
Дата: 17.11.06 15:33
Оценка: +1 -2
Здравствуйте, Erop, Вы писали:

E>Для людей, которым так нравится слово unsigned написанное не в комментарии к методу, а в имени типа возвращаемого значения я предлагаю поступать так:


E>
E>typedef int int_for_unsigned_values;
E>


E>И читабельно всё станет и совместимо и вообще со всех сторон прекрасно.


Совет, по своей сути примерно эквиватентный предложенному в соседнем сообщении варианту с различными типами в DEBUG и не DEBUG ("Безумью храбрых" и т.п.)
Best regards,
Андрей Тарасевич
Re[6]: мои измышления про unsigned, size_t и стандарт
От: Erlond Россия  
Дата: 18.11.06 11:33
Оценка: -1 :))

Теперь предлагаю посмотреть на это дело с другой стороны.
В конце концов переносимость C++ программ -- это миф.
Попробуйте написать сложную программу, которая легко переживёт перенос на платформу сильно другой разрядности. Скажем из 32-бит в 16?
Нифига у вас не выйдет. Всё равно переполнения будут вас преследовать и всякие другие проблемы.


Ну почему же миф? Всё вполне реально. Просто не нужно в коде использовать константы, указывающие размеры типов данных, всё определять через sizeof, а сами типы данных привести в соответствие с размером слова целевой платформы, т.е. int — 16 бит, и т.д.
Re[14]: unsigned
От: Пётр Седов Россия  
Дата: 15.11.06 18:14
Оценка: 36 (1) +1
Здравствуйте, Erlond, Вы писали:

E>Интересные аргументы приводятся "противниками" типа unsigned int.

Вряд ли здесь есть противники unsigned. Этот тип хорошо подходит для танцев с битами. Речь идёт об опасности беззнаковой арифметики.

E>В основном всё сводится к тому, что "ну не надо знаковую величену представлять безннаковой".

Нет, речь идёт о том, чтобы использовать int даже для неотрицательных ("зуб даю") чисел.

E>Количество — unsigned int, а разница — int.

Без приведений типа разница — тоже unsigned.

E>И ещё меня, допустим, удивляет реализация CArray, где метод GetSize() возвращает int.

Это перестанет удивлять после дня, потраченного на поиск ошибки из-за беззнаковой арифметики.

E>Размер массива может быть отрицательным??

Нет, длина массива всегда >= 0. Но в одном выражении с CArray::GetSize может участвовать отрицательное число. Если ошибочный результат подвыражения не сохраняется в переменной, то ошибку найти тяжело. Например, здесь
Автор: Кирпа В.А.
Дата: 20.09.04
.

E>А программист должен знать типы данных языка.

Да. Например, желательно знать, что unsigned char и unsigned short в выражениях продвигаются (promote) до int (а не unsigned) и не вызывают беззнаковую арифметику (на современных платформах).
Также в языках C/C++ нет типов unsigned float и unsigned double, но пока никто не жаловался, что масса (объём, ...) хранится в переменной знакового типа. Аргументов вроде "Разве может масса быть отрицательной?" не слышно.

E>С++ не прощает легкомысленного программирования.

Да, поэтому отладочные проверки нужно делать самостоятельно. Например, с помощью assert-а.

R>>Но никакого "а типа вроде как количество товара не может быть отрицательным... заведу-ка я для него unsigned... ой а что это у меня получилось 4 миллиарда товаров?".

E>А что, лучше когда у нас получается -5 единиц товара?
Конечно лучше. Ближайший assert обнаружит это:
int Count;
...
assert(Count >= 0);

В случае unsigned условие бессмысленно.

E>Почему странно получить 4 млрд, а -5 — нормально?

Это не нормально, это ошибка, но в случае int-а её можно обнаружить, а в случае unsigned — нет.

E>P.S. Андрею Тарасевичу — большой респект

За что? За то, что направляет новичков на грабли (беззнаковая арифметика)?
Пётр Седов (ушёл с RSDN)
Re[5]: Нужен ли unsigned
От: Кодт Россия  
Дата: 14.11.06 09:54
Оценка: 7 (1) +1
Здравствуйте, remark, Вы писали:

Практически согласен со всем, кроме вот этого

R>Обратных же примеров, когда замена unsigned на signed ломает код, нет!

R>Если не считать, что у unsigned чуть больше диапазон. Но стоит ли оно того? Если уж надо хранить действительно большие числа, то имхо лучше воспользоваться int64_t. Тут и диапазон действительно больше, чем у int и проблем не будет.

Как только мы начинаем упражняться в работе с битами, проблемы сразу же появляются.
— приведение типов (всем хорошо известно, как переводить char в int: (int)(unsigned char)ch)
— сдвиг (SHR для беззнаковых и SAR для знаковых)
— битовые поля
struct bitz
{
    unsigned u : 1; // принимает значения 0 и 1
    int      i : 1; // принимает значения... сюрприз! 0 и -1, потому что старший (единственный) бит - знаковый
};
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[13]: Видимо ошибка в кончерватории :)
От: Erlond Россия  
Дата: 16.11.06 18:00
Оценка: 6 (1) :)
Здравствуйте, Erop, Вы писали:

Вот скажем такая простая штука, как unsigned(-1) % 10 уже равна неизвестно чему)


Очень просто, в компльютере числа представляются в дополнительном коде. Дополнительный код положительного числа равен самому числу, а чтобы получить дополнительный код отрицательно числа, нужно празрядно проинвертировать число, а затем, к тому что получилось прибавить 1.

Возьмём ваш пример с"-1" для 32-х разрядного регистра

"1" — это 0x00000001,

проинвертируем поразрядно, получим:

0xFFFFFFFE

Теперь прибавим единицу, получим:

0xFFFFFFFF

Таким образом дополнительный код числа "-1" — 0xFFFFFFFF, при приведении типов, в переменную типа unsigned int запишется именно 0xFFFFFFFF, в десятичной системе счисления это составляет 4 294 967 295. Явно видно, что остаток деления на 10 будет 5.
Re[19]: Видимо ошибка в кончерватории :)
От: Erlond Россия  
Дата: 18.11.06 09:24
Оценка: 6 (1) +1
Здравствуйте, Erop, Вы писали:

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


E>>А в чём, собственно, вопрос?


E>В чём состоит практическая выгода unsigned типов? Вот в чём практические потери и трудности я подробно разъяснил. А в чём таки состоит выгода --


Для меня "выгоды" состоят в следущем:

1. Не вижу смысла использоваться знаковые целые для величин, которые не будут отрицательными -> дополнительная информация тому, кто будет использовать код
2. Т.к. нет отрицательных значений убирается проверка на то, что значение выскочило "ниже" положенного. То, что удобно ловить ошибки по отрицательным — не соглашусь, ошибку нужно ловить перед выполнением операции.
3. Если в коде с беззнаковой арифметикой содержится ошибка, то она очень быстро даст о себе знать, в отличие от знаковой, на которой до поры, до времени всё будет работать, а когда ошибка даст о себе знать, то тогда уже может понадобиться ни день, и не два на отладку. Вполне возможно, что всё будет работать до самого релиза. Статья на тему
Автор(ы): Dr. Joseph M. Newcomer
Дата: 18.06.2001
Статья посвящена проблемам перехода с Debug-версии на Release-версию. Рассматриваются
типичные ошибки, которые могут не проявляться в отладочной версии, но проявляются в финальной.
Обсуждается вопрос "ошибок компилятора" и вопросы необходимости оптимизации и ее побочные эффекты.
В последней редакции добавлен раздел посвященный проблеме совместимости динамических библиотек.
Re[7]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 13.11.06 15:29
Оценка: 3 (2)
Здравствуйте, johny5, Вы писали:


АТ>>
АТ>>int a[N];
АТ>>int* p = a + N;

АТ>>while (--p >= a)
АТ>>  *p = 0;
АТ>>


АТ>>Типичный 'int'-овый программист зачатсую даже и не видит проблемы в этом коде. Более того, такой код зачастую "работает". В то время как на самом


J>Что то я действительно не вижу проблем в таком коде...


В один прекрасный момент 'p' станет указывать на начало массива. К такому указателю в языках С/С++ запрещается применять операцию '--', т.е. запрещается пытаться получить указатель на элемент "перед первым" элементом массива. После последнего — можно, перед первым — нельзя. Попытка получить такой указатель приведет к неопределенному поведению. Этот код как раз попытается получить такой указатель.
Best regards,
Андрей Тарасевич
Re[14]: Ответ другого оппонента :)
От: Erlond Россия  
Дата: 16.11.06 07:56
Оценка: 3 (1) :)
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Здравствуйте, Erop, Вы писали:


АТ>>>(Другому оппоненту: а модульную арифметику, кстати, тоже придумали математики...)


E>>ваша правда, товарищ эксперт, но таки когда математики думали о модульной арифметике, они как-то не ограничивали себя в выборе модуля между 0x100, 0x10000, 0x100000000 и 0x10000000000000000


АТ>Это еще что! Когда они думали об обычной арифметике, они также не ограничивали себя диапазоном -0x80000000..0x7FFFFFFF. И даже диапазоном 0x8000000000000000..0x7FFFFFFFFFFFFFFF не ограничивали! Я слышал историю про то, как в древности один мужик за изобретение какой-то игры (поддавки, кажется) затребовал 2^64-1 пшеничных зерна. И это было тогда, до инфляции...


Вообще-то это были шахматы, а дело было в Древней Индии. В оригинале было так:какому-то мудрецу поруили придумать военную игру, дабы правителю Индии не было скучно. Он придумал шахматы, и когда изобретателя шахмат спросили, что он хочет в награду за изобретение игры, он ответил так — "на 1 клетку доски положите мне 1 зерно, на 2-ю — два, на 3-ю 4 зерна..", и т.д.
Правитель посмеялся над этим, и распорядися выдатть ему зерно. Но... его расстроили математики — они считали несколько недель, какое количество зерён требуется выдать, а потом объявили, что такого колоичества зерна нету во всей Индиии...

Как вариант решения — заставить изобретателя отсчитывать вручную зёрна, много бы не насчитал
Re[5]: Нужен ли unsigned
От: Шахтер Интернет  
Дата: 14.11.06 15:28
Оценка: 2 (1) :)
Здравствуйте, remark, Вы писали:

R>Здравствуйте, Андрей Тарасевич, Вы писали:


АТ>>Беззнаковые по своей природе сущности естественно представлять беззнаковыми типами. Тут, собственно, и вопросов никаких нет.


R>Я всеми руками за типизацию.


Типизация здесь не причем. Вообще.

R>Если у переменной только два значения, то надо использовать bool, а не int. Если значение не меняется, то надо использовать const. Это замечательно, когда компилятор отлавливает ошибки. Это надо использовать всегда. Всегда, за исключением одного случая. Не надо использовать unsigned. Почему? Из-за реализации в языке. Проблема в том, что компилятор не отловит ошибки. Ну не отловит он и всё. И это получается ещё хуже, т.к. появляется чувство ложной уверенности. Думаешь, я завёл unsigned — всё, все мои проблемы решены. А на самом деле ничего не решено и компилятор практически ничего не контролирует.


R>Я могу, конечно, поприводить примеры типа таких:


R>
R>    unsigned u = 0;
R>    int i = 0;
R>    u = i;
R>    i = u;
R>    // msvc80sp1 уровень предупреждений 4 — ни одного варнинга. Хотя оба из присваиваний могут вызвать проблемы...
R>


R>
R>    std::vector<int> v (3);
R>    for (size_t i = v.size() - 1; i >= 0; --i)
R>        std::cout << v[i];
R>


R>Или вот ещё статья недавно проскакивала.


R>Но достаточно просто оценить какой шум вокруг этой темы вот уже на протяжении десятилетий. Десятилетиями программисты наступают на одни и те же грабли. Причём не самые плохие программисты (и вы предлагаете понаступать на них ещё немного всем нам). Почему? Они тоже надеются, что компилятор им чем-то поможет. Они тоже думают, что они повышают типизацию.


Этот шум не стоит выеденного яйца. Беззнаковые типы широко используются в программировании и будут использоваться, поскольку без них многие задачи вообще не решаются. Так что нужно не шуметь, а просто выучить беззнаковую арифметику и научится грамотно её использовать -- там где она необходима.
Ну и кстати, понимание того, где какую арифметику нужно использовать тоже приходит со знаниями и опытом.

R>Фразы типа:

R>

R>я считаю, что правильнее внимательнее относиться к коду, а не пытаться компенсировать лень использованием знаковых типов

R>Это из идеального мира. Действительно, давайте просто внимательно писать программы без ошибок.
R>В реальном мире, к сожалению, не так. Программисты работают по вечерам, по 12 часов, в спешке и т.д. Все мы писали и одинарное равно в if'е вместо двойного, и код типа примера выше и т.д.

R>И очень бы хотелось, что бы при написании программ не надо было проявлять чудеса внимательности и памяти.


Это невозможно. Память, внимательность и хорошее понимание как нужно решать задачу -- это основа успешной работы программиста.

R>

R>знаковые типы просто-напросто чаще "прощают" беспечное отношение к коду


R>Знаковые типы не просто прощают беспечное отношение к коду, они действительно заставляют больше кода работать корректно. Почувствуйте разницу. Посмотрите на цикл вверху. Что бы заставить его работать достаточно просто заменить size_t на int. Всё. Код будет корректным и рабочим.


Нет, не будет. v.size()-1 не обязательно представимо положительным int. Фокус не удался.

    std::vector<int> v (3);
    for (size_t i = v.size() - 1; i!=size_t(-1) ; --i)
        std::cout << v[i];


Можно сделать вот так.

    std::vector<int> v (3);
    for (size_t i = v.size() ; i-- ;)
        std::cout << v[i];


Но лучше вот так.

R>Посмотрите пример в статья. Всё что достаточно сделать, что бы там код заработал. Правильно. Заменить unsigned на int.


R>Работу этого кода сломало единственное — замена signed на unsigned. Причём тоже из благих намерений. В цикле мы по каким индексам хотим пробежать? От size()-1 до 0. Может быть отрицательным? Нет. Заменяем signed на unsigned — код перестаёт работать!


R>В примере в статье процент в каком диапазоне может быть? От 0 до 100. Может быть отрицательным? Нет. Заменяем signed на unsigned — код (опять) перестаёт работать!


R>Я думаю таких примеров можно найти ещё.


Примеров откровенного ламерства, когда люди простейший цикл не могут написать, действительно можно найти вагон и прицепную тележку.

R>Обратных же примеров, когда замена unsigned на signed ломает код, нет!


Постановка вопроса некорректна. Это примерно тоже самое, что экспериментирвать, что будет если в топливный бак вместо саляры залить бензин или наоборот.
Сломается японская пила или нет?

R>Если не считать, что у unsigned чуть больше диапазон. Но стоит ли оно того? Если уж надо хранить действительно большие числа, то имхо лучше воспользоваться int64_t. Тут и диапазон действительно больше, чем у int и проблем не будет.


Проблемы тут будут те же самые. Ну нет в компьютере натуральных чисел и не будет.
Точно так же нет вещественных, и всё что мы имеем -- это жалкий float.

R>Я недавно думал над этим вопросом. И изначально тоже отталкивался от точки, что всё должно быть максимально типизировано. И что надо использовать unsigned. Но потом после анализа таких примеров и кучи блогов, статей, постов по поводу ошибок связанных с unsigned, пришёл к указанному выводу — типизация везде, кроме unsigned. Ну не работает оно так как хочется. Не работает.


R>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[5]: Где тут ошибка
От: Erop Россия  
Дата: 14.11.06 09:39
Оценка: 1 (1) +1
Здравствуйте, Андрей Тарасевич, Вы писали:

E>>1) реально size таким большим не бывает, так как в память плохо помещается

АТ>Ни предел типа 'size_t', ни предел типа 'int' никак не связаны с "помещаемостью в память".

Ну в программировании вообще всё задачами определяется. Область деятельности-то прагматическая
Вот в обсуждаемой задаче -- итерации массива, мало есть возможностей завести такой массив, чтобы знаково/беззнаковые дыры сказались
А в каком-то абстрактном вычислительном алгоритме использовать для итерации unsigned, КМК, себе дороже.
Скажем для итерации слоёв в вычислительной схеме. Таки из номера слоя что-нибудь вычитать иногда хочется
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 20:43
Оценка: 1 (1) +1
Здравствуйте, Аноним, Вы писали:

А>>>Я решил попробовать писать "правильный" код. Для ширины например — unsigned, т.е. она не бывает отрицательной. И тд.

А>>>Но как меня всякие мелочи задолбали, извините. Чуть чуть перепутал, и всё, 4 миллиарда, вся логика валится.

C>>Нужно обращать внимание на warning’и компилятора. И иметь компилятор, который их сыплет по всякому поводу.


А>gcc, -Wall -Wextra

А>варнингов нет. Да и откуда ему знать, что получится при m_width — m_pageWidth: 10 или 0 или -10

Правильность вычитания проверяется перед вычитанием. Даже в случае знаковых типов. Пытаться проверять вычитание "посмертно" — это примерно то же самое, что пытаться отлавливать деление на ноль после собственно самого деления...
Best regards,
Андрей Тарасевич
Re[16]: Эх, товарищ, товарищ...
От: vsb Казахстан  
Дата: 15.11.06 17:39
Оценка: 1 (1) +1
Здравствуйте, Erlond, Вы писали:

E>Ну почему же, всё зависит от задачи. Если разница между двумя unsigned не превышает INT_MAX, то следующий код вполне работоспособен.


E>
E>unsigned int i = 3;
E>unsigned int j = 5;
E>int r = i-j;
E>std::cout << "r = " << r << std::endl;
E>

E>Результат:
E>
E>r = -2
E>


Строго говоря, здесь, по 4.7.3, implementation-defined behaviour.
Re[6]: Нужен ли unsigned
От: Кодт Россия  
Дата: 13.11.06 11:38
Оценка: +2
Здравствуйте, Шахтер, Вы писали:

К>>В знаковой арифметике одно и то же неравенство можно выразить несколькими способами: x<y, x-y<0, 0<y-x, а в


Ш>В знаковой арифметике эти выражения точно так же не эквивалетны. Кроме того, x<0 не эквивалетно -x>0.


Ну не "точно так же". Конечно, в области больших чисел есть риск поймать переполнение.
Но предусловие "оба числа по абсолютному значению не превосходят MAXINT/2" достаточно распространено, и этим можно пользоваться.

Кстати говоря. Это и плюс, и минус одновременно. С одной стороны, упрощаются выражения, а с другой — есть риск забыть проверки и получить феерверк на больших значениях. Беззнаковая же арифметика не прощает халатности с самого начала.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[2]: Нужен ли unsigned
От: Sm0ke Россия ksi
Дата: 13.11.06 12:26
Оценка: :))
Здравствуйте, Шахтер, Вы писали:


Ш>3) В C/C++ размерности массивов выражаются беззнаковым типом size_t. По этой причине ипользовать для индексирования знаковые типы -- создавать потенциальные дыры.


Можно написать свой вектор, где отрицательный индекс ведёт отсчёт с конца.

my_vector vec(10);
//vec[-1] == vec[9]
Re[6]: Где тут ошибка
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 14:55
Оценка: +1 :)
Здравствуйте, Erop, Вы писали:

E>Скажем для итерации слоёв в вычислительной схеме. Таки из номера слоя что-нибудь вычитать иногда хочется


Необходимость "что-то вычитать" никак не служит аргументом в пользу знакового типа. Из беззнакового типа тоже можно "что-то вычитать". Если в предметной области допустимы только положительные значения, то получиение отрицательного значения в знаковом типе ничем принципиально не отличается от получения черезменрно большого значения в беззнаковом. Разница только в том, что, как тут уже говорилось, со знаковым типом придется ловить обе ситуации (выход за пределы вниз и вверх), а с беззнаковым только одну. Это, как раз таки, аргумент в пользу беззнакового типа.
Best regards,
Андрей Тарасевич
Re[8]: Нужен ли unsigned
От: Кодт Россия  
Дата: 14.11.06 16:44
Оценка: +2
Здравствуйте, Шахтер, Вы писали:

Ш>Я честно не понимаю, если нужно узнать, что больше x или y, то зачем писать

Ш>x-y<0 вместо x<y ? Зачем искуственно сужать область правильной работы функции?

К>>Кстати говоря. Это и плюс, и минус одновременно. С одной стороны, упрощаются выражения, а с другой — есть риск забыть проверки и получить феерверк на больших значениях. Беззнаковая же арифметика не прощает халатности с самого начала.


Ш>Я бы всё-таки хотел более конкретных примеров, как упрощаются выражения.


Пожалуйста. Пусть даны 4 числа, задающие отрезки [a;b] и [c;d]. Нужно выяснить, какое значение — b-a или d-c — больше. При том, что в предусловии не сказано, что a<=b и c<=d.

Естественное предусловие — |a|,...,|d| < MAXINT/2.
bool ab_less_than_cd = b-a < d-c; // интуитивно понятное (справедливо только для signed)

bool ab_less_than_cd = b+c < a+d; // для случая unsigned, избавились от вычитания... что за величины такие странные: b+c? a+d?

bool ab_less_than_cd = (int)(b-a) < (int)(d-c); // мы утверждаем, что разность - знаковая величина.
// Окей, как насчёт unsigned short или unsigned long? Нужно ввести некий signed_cast, приводящий к знаковому типу подходящего размера

bool ab_less_than_cd = a<b && (d<=c || b-a<d-c) || b<=a && (c<d || c-d<=a-b); // код, свободный от граничных условий... ничерта не понятный и возможно, с ошибками
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[8]: Где тут ошибка
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 17:46
Оценка: -1 :)
Здравствуйте, Erop, Вы писали:

АТ>>Необходимость "что-то вычитать" никак не служит аргументом в пользу знакового типа. Из беззнакового типа тоже можно "что-то вычитать". Если в предметной области допустимы только положительные значения, то получиение отрицательного значения в знаковом типе ничем принципиально не отличается от получения черезменрно большого значения в беззнаковом. Разница только в том, что, как тут уже говорилось, со знаковым типом придется ловить обе ситуации (выход за пределы вниз и вверх), а с беззнаковым только одну. Это, как раз таки, аргумент в пользу беззнакового типа.


E>Нет уж. Числа лучше бы использовать нормальные.

E>И отлаживать проще и программировать и всё такое.

Не вижу в этом сообщении содержания. Соответственноо и ответить ничего содержательного не могу.
Best regards,
Андрей Тарасевич
Re[6]: Всё очень просто....
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 20:39
Оценка: +2
Здравствуйте, Erop, Вы писали:

E>1) Вообще беззнаковая арифметика нужна в C++ в основном для того, чтобы работать со всякими странными объектами, которые на самом деле числами не являются, но от чего-то в C и С++ числами предстваленны.


Неправда. Такими словами можно выразиться только ою одном типе в С/С- типе 'unsigned char'.

E>Вот в паскале нету никакой беззнаковой арифметики и ничего.


А это уже смотря что имеется в виду под "беззнаковой арифметикой". В общем — неправда. В Паскале есть диапазонные типы. Использоание беззнаковых типов в С/С++ для представления беззнаковых величин — это как раз и есть грубый аналог использования правильно заданнного паскалевского диапазонного типа. Так что это не в Паскале чего-то нет, а как раз таки в С/С++ чего-то нет — нет диапазоннных типов. А использование беззнаковых типов в С/С++ — это лишь способ "апрроксимировать" данную паскалевскую идею.

E>Да и в математике тоже нету


Опять неправда.

Ш>>Это утверждение мне непонятно. А что гарантирует знаковость числа?

E>Тоже ничего не гарантирует, кроме того, что труднее попасть в переполнение по вычитанию

И проще — по сложению. Причем ровно на столько же.

E>Но в целом в математике и вообще в мозгу нормального среднего человека числа вполне себе знаковые.


Ни в коем случае. Количественные величины "в мозгу нормального среднего человека" строго беззнаковы.

E>И в предметной области тоже занковые.


Это утверждение настолько же верно и полезно, как и утверждение, что "в предметной области" все числа — с плавающей точкой.
Best regards,
Андрей Тарасевич
Re[9]: Нужен ли unsigned
От: kan Великобритания  
Дата: 15.11.06 09:12
Оценка: -1 :)
Кодт wrote:

> Пожалуйста. Пусть даны 4 числа, задающие отрезки [a;b] и [c;d]. Нужно

> выяснить, какое значение — b-a или d-c — больше.
А что это означает по смыслу? Может ты хотел померить у кого длиннее? Тогда abs(b-a) < abs(d-c)
А коли так, то лучше ввести функцию:
inline unsigned length(unsigned x, unsigned y){return x>y?x-y:y-x;}

тогда всё просто
bool ab_less_than_cd = length(a, b) < length(c, d);

А если ты не очепятался, то
bool ab_less_than_cd = b+c < a+d; // для случая unsigned, избавились от вычитания... и величины не более странные, чем 
b-a, d-c
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[6]: А почему так "немножечко нервно"? :)
От: Шахтер Интернет  
Дата: 15.11.06 09:14
Оценка: +1 -1
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Шахтер, Вы писали:


Ш>>А то что без беззнаковых типов невозможно писать надежный и переносимый код в этом и во многих других случаях.

E>Ну это просто враньё

Враньё -- оно в твоих постах. Через один.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[12]: Ответ другого оппонента :)
От: Erop Россия  
Дата: 15.11.06 15:14
Оценка: +1 :)
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>(Другому оппоненту: а модульную арифметику, кстати, тоже придумали математики...)


ваша правда, товарищ эксперт, но таки когда математики думали о модульной арифметике, они как-то не ограничивали себя в выборе модуля между 0x100, 0x10000, 0x100000000 и 0x10000000000000000
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[14]: Эх, товарищ, товарищ...
От: remark Россия http://www.1024cores.net/
Дата: 15.11.06 15:53
Оценка: +2
Здравствуйте, Erlond, Вы писали:

E>Количество предметов — беззнаковая величина, она всегда положительна, а разница в количестве может быть как положительной,

E>так и отрицательной. Так в чем проблема-то? Количество — unsigned int, а разница — int.

Хороший пример
Вот именно, что логично полагать, что разница — это int. Однако, если повнимательнее посмотреть, как работает с++, то можно удивиться. Разница между двумя количествами (unsigned) — это тоже unsigned! Не int!


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 16.11.06 16:24
Оценка: :))
Здравствуйте, Максим2006, Вы писали:

М>Предлагаю послушать старейшин... (Б.Стр-п, 2005)


Советы "старейшин" обычно обладают рядом свойств, который надо иметь в виду. Во-первых, "старейшин" много: одни советуют одно, другие — другое (как известно, "старейшина" С (Керниган, кажется) считал модификатор 'const' бесполезным). Во-вторых, эти советы могут отличаться (зачастую — до наоборот) в зависимости от целевой аудитории: новичкам правильнее посоветовать одно, опытным программистам — другое. В-третьих, те же самые старейшины имеют свойство менять свое мнение: вчера они считали так, сегодня — эдак, а завтра — еще как-нибудь. В-четвертых, есть "старейшины"-теоретики, а есть "старейшины"-практики и их советы могут существенно отличаться (я, кстати, никак не подразумеваю, что советы "практиков" ценнее советов "теоретиков"). И т.д.

В общем, "старейшин" надо уважать, но, скажем так, понимать, что все, что они говорят — это лишь монетка на ту или иную чашу весов. И, возможно, предназначавшаяся совсем не для ваших весов...
Best regards,
Андрей Тарасевич
Re[2]: Советы Страуструпа
От: Пётр Седов Россия  
Дата: 16.11.06 18:00
Оценка: +2
Здравствуйте, Максим2006, Вы писали:
М>Предлагаю послушать старейшин...
Страуструп пишет в книге "Язык программирования C++" (третье издание) в конце главы 4:

4.10. Советы
...
[18] Избегайте беззнаковой арифметики; § 4.4.
[19] С подозрением относитесь к преобразованиям из signed в unsigned и из unsigned в signed; § В.6.2.6.

Пётр Седов (ушёл с RSDN)
Re[3]: Нужен ли unsigned
От: Michael7 Россия  
Дата: 16.11.06 20:21
Оценка: +2
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>В общем, "старейшин" надо уважать, но, скажем так, понимать, что все, что они говорят — это лишь монетка на ту или иную чашу весов. И, возможно, предназначавшаяся совсем не для ваших весов...


Лично я усвоил для себя одно простое правило -- когда за переменными скрываются хоть сколько-нибудь физически реальные по смыслу величины, то очень вредно делать для них ограничивающие предположения.

Приведу иллюстрирующий пример, хотя и не связанный со знаковостью. Я как-то участвовал в написании системки для работы с некоторыми специфическими документами для одной из госорганизаций. Особенность этих документов в том, что по-идее не могли никак, ну никак не могли иметь разные документы одинаковый номер -- это не просто так документы были, с этим номером государственная организация выдаёт Важные Бумаги и не может быть одинакового номера на бумаге для Лица А и Лица Б. Вы, наверное, уже догадались, что когда системка прошла тестирование и была введена в эксплуатацию выяснилось, что невозможное всё-таки оказалось иногда возможно Для руководства этой организации сей факт стал скандальным. Хорошо, что этот номер не сделали уникальным ключом в базе, хотя и хотели сильно.
Re[7]: Мои извращённые желания
От: Erop Россия  
Дата: 17.11.06 14:44
Оценка: +1 :)
Здравствуйте, Erlond, Вы писали:

E>Это и есть -2 в доп. коде


E>
E>    int a = 0xFFFFFFFE;
E>    std::cout << a;
E>



И что с того?
Кстати то, что этот код выведет "-2" -- это UB

Но вообще мне всё равно надо не "-2 в доп. коде для регистра такой-то разрядности", а просто -2 число такое.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[20]: Видимо ошибка в кончерватории :)
От: Michael7 Россия  
Дата: 18.11.06 10:36
Оценка: +2
Здравствуйте, Erlond, Вы писали:

E>Для меня "выгоды" состоят в следущем:


E>1. Не вижу смысла использоваться знаковые целые для величин, которые не будут отрицательными -> дополнительная информация тому, кто будет использовать код


А я вижу. Насмотрелся ситуаций, когда по разным причинам невозможное становится возможным. И -8 буратин оказываются даже не ошибкой в программе, а вполне естественным значением, которое поддаётся правильной интерпретации. И если где и есть ошибка, то не в программе, а в самой постановке задачи, когда всем казалось, что -8 буратин не может быть в принципе.

E>2. Т.к. нет отрицательных значений убирается проверка на то, что значение выскочило "ниже" положенного. То, что удобно ловить ошибки по отрицательным — не соглашусь, ошибку нужно ловить перед выполнением операции.


Да, с unsigned можно ловить сделанные ошибки переполнения. После операции сложения. После умножения уже никакой гарантии. Я к тому, что на мой взгляд ловля ошибок переполнения постфактум вообще нежелательна в рабочем коде.

E>3. Если в коде с беззнаковой арифметикой содержится ошибка, то она очень быстро даст о себе знать, в отличие от знаковой, на которой до поры, до времени всё будет работать, а когда ошибка даст о себе знать, то тогда уже может понадобиться ни день, и не два на отладку. Вполне возможно, что всё будет работать до самого релиза. Статья на тему
Автор(ы): Dr. Joseph M. Newcomer
Дата: 18.06.2001
Статья посвящена проблемам перехода с Debug-версии на Release-версию. Рассматриваются
типичные ошибки, которые могут не проявляться в отладочной версии, но проявляются в финальной.
Обсуждается вопрос "ошибок компилятора" и вопросы необходимости оптимизации и ее побочные эффекты.
В последней редакции добавлен раздел посвященный проблеме совместимости динамических библиотек.
Смесь знакового и беззнакового тоже может порождать странные ошибки на которые как раз и уйдёт ни день и не два на отладку. А такая смесь может возникнуть, если есть хоть одна операция вычитания.


Повторюсь. Собственно, я не против беззнаковых типов. И думаю, что никто не против из спорящих здесь. Вопрос только в том, где их уместно применять, а где нет. Я вот считаю, что для величин, участвующих в арифметических операциях их применение весьма нежелательно. Тем более для переменных, отражающих какие-то физические реалии, даже если они по замыслу неотрицательные.
Re[18]: Большие числа
От: Пётр Седов Россия  
Дата: 27.04.07 02:35
Оценка: +1 -1
Здравствуйте, Sinclair, Вы писали:
ПС>>>>А вот код со знаковой арифметикой часто не содержит ошибок просто потому, что вычисляется именно то, что имел в виду программист.
S>>>Нет. Код со знаковой арифметикой как правило содержит ошибки, просто они редко проявляются. Я уже приводил пример вычисления среднего значения. Вот он:
S>>>
S>>>int aver(int a, int b)
S>>>{
S>>>  return (a + b) / 2;
S>>>}
S>>>


S>>>Он, конечно же, вычисляет именно то, что имел в виду программист. Но не всегда. Давайте посчитаем среднее от, к примеру, (2000000000 и 2000000000), а? Каждое число является вполне нормальным знаковым 32-х разрядным целым. Результат тоже. Но программист, наверное, имел в виду получить всё же 2000000000, а не -147483648, не так ли?

ПС>>Такой пример можно придумать для любого арифметического типа фиксированного размера (например, 32 бита), в том числе для unsigned int. Поэтому Ваш пример не относится к спору «знаковая арифметика vs. беззнаковая арифметика». Ваш пример относится к спору «фиксированная арифметика vs. динамическая арифметика».
S>Мой пример относится к утверждению "вот код со знаковой арифметикой часто не содержит ошибок".
По моим понятиям, функция aver не содержит ошибок. А числа порядка миллиарда – это большая экзотика. 32-битного int-а хватает почти всегда с хорошим запасом.
Пётр Седов (ушёл с RSDN)
Re[6]: Всё очень просто....
От: Centaur Россия  
Дата: 15.11.06 09:55
Оценка: 12 (1)
Здравствуйте, MaximE, Вы писали:

ME>Забавно, что без unsigned невозможно хранить в однобитовом члене 1. С signed

ME>только -1 и 0.

Строго говоря, реализация может представлять знаковые числа не в дополнительном коде, а например, в виде «знак+мантисса». Тогда будет +0 и -0
Re[14]: Беззнаковые иллюзии
От: Пётр Седов Россия  
Дата: 18.12.06 16:28
Оценка: 9 (1)
Здравствуйте, johny5, Вы писали:
J>Хорошо, но вы согласны, что unsigned даёт просто больше декларативной информации чем int (целое и положительное vs целое)?
Да. Но, во-первых, эта декларативность не подкрепляется run-time-проверками (в широко используемых компиляторах).
Во-вторых, арифметика с unsigned int беззнаковая. В простых случаях (например, итерация массива в прямом порядке) беззнаковая арифметика не вызывает проблем. Но когда появляется беззнаковое вычитание, риск ошибиться возрастает (так как беззнаковая арифметика отличается от обычной в районе нуля). Беззнаковая арифметика — низкоуровневая техника. Она позволяет выжать из компьютера максимум (дополнительный бит), но за это приходится платить. Код с беззнаковой арифметикой хрупкий, подвержен ошибкам. От программиста требуется повышенное внимание/напряжение, иначе любое изменение кода может незаметно внести ошибку (которая проявляется только в граничном случае; например, когда vec.size() = 0). А вот код со знаковой арифметикой часто не содержит ошибок просто потому, что вычисляется именно то, что имел в виду программист. Так что беззнаковую арифметику лучше избегать. А если уж использовать (в исключительных случаях), то изолировать в классе или функции.
Для обработки целых чисел вместо unsigned int лучше использовать int + assert. Во-первых, assert гораздо более выразителен, чем модификатор 'unsigned' (по которому не скажешь, является ли ноль допустимым значением). Например:
void SetWeights(int Count, double Weight)
{
  assert(Count > 0);
  assert(Weight > 0.);
  ...
}

Такие ограничения не выразить с помощью модификатора 'unsigned' (тем более что типа 'unsigned double' просто нет).
Во-вторых, в отличие от модификатора 'unsigned', assert делает run-time-проверку (в Debug-конфигурации) и сигналит (MessageBox, abort, DebugBreak, исключение, ...), если условие не выполняется. То есть не будет такого, что -1 молчаливо преобразуется в 4 294 967 295 и цикл выполняется четыре миллиарда раз.
Кстати, assert может сообщать полезную информацию не только программисту, но и компилятору. Например, в MSVC6 assert можно определить так:
#ifdef _DEBUG
  ...
#else // Release-конфигурация
  #define assert(Cond) __assume(Cond)
#endif

Это позволяет генерировать такой же оптимальный ассемблерный код, как и для unsigned int. Например, если есть переменная n типа int и код содержит 'assert(n >= 0)', то компилятор имеет право (в Release-конфигурации) транслировать выражение 'n / 8' в одну инструкцию битового сдвига (на 3 бита вправо, так как 8 = pow(2, 3)).
Пётр Седов (ушёл с RSDN)
Re[8]: Нужен ли unsigned
От: vsb Казахстан  
Дата: 13.11.06 11:08
Оценка: 6 (1)
Здравствуйте, night beast, Вы писали:

NB>если не ошибаюсь, сравнение с указателем который указывает не на "элемент массива или элемент после конечного" -- UB.


NB>зачем так мне не известно.


Здесь можно почитать дискуссию по этому поводу: http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/756952acd8905e18/639bcb0527d875c2

Например
The 80386 memory access model is quite
complicated and there are many ways to implement a "pointer".
One involves a pair (selector,offset) and loading a wrong selector
in any of the selector registers is an error (General Protection Fault
if I remember correctly). Deleting an object could result in freeing
the entry in a selector translation table and subsequent load of the
pointer value could fail.
Re[4]: Как дешево и предсказуемо!
От: Андрей Тарасевич Беларусь  
Дата: 16.11.06 17:25
Оценка: 6 (1)
Здравствуйте, Erop, Вы писали:

АТ>>В общем, "старейшин" надо уважать, но, скажем так, понимать, что все, что они говорят — это лишь монетка на ту или иную чашу весов. И, возможно, предназначавшаяся совсем не для ваших весов...


E>Итак. "Тарасевич vs Страуструп" -- куму поверим?


О, смотрите-ка! Несколько сообщений назад товарищ Erop вынес в заголовок своего сообщения фразу "А ты кто такой?", тем самым подразумевая, что я якобы сказал ему что-то подобное. На самом деле ничего подобно я ему тогда не говорил, в чем несложно убедиться, перечитав мое сооветствующее сообщение. Т.е. товарищ Erop просто решил немножко наврать, рассчитывая на то, что в такой большой дискуссии какие-то пользователи ограничаться "чтением заголовков" не вникая в суть.

А вот здесь мы наблюдаем соврешенно явное и неприкрытое то самое "А ты кто такой?". И исходит оно от кого? Правильно — от того самого Erop-а! И самое интересное, что опять же мы имеем случай того же самого вранья. И опять же это вранье вынесено в заголовок сообщения. В то время как никакого "Тарасевич vs Страуструп" в моем сообщении и близко не содержится.

Набивший оскомину (мне, по крайней мере) пример: мы все прекрасно знаем (или, по крайней мере, многие из нас), что, например, в известной книге по С++ того же Страуструпа содержатся заведомо ошибочные утверждения, типа утверждения о наличии конструктора у целочисленных типов. Более того, Страутруп сам прекрасно знает, что это утверждение ошибочно. И все прекрасно понятно, почему эта умышленная "ошибка" сделана. Когда я (например — я), утверждаю, что это утвержддение ошибочно, никакого "Тарасевич vs Страуструп" подтекста в таком утверждении нет. Тем не менее, когда этот вопрос возникает в обсуждении, почти всегда надется горлопан, который начнет орать что-то на тему "Тарасевич vs Страуструп". Дешево и предсказуемо. Но зачем — непонятно.

E>Страуструп пишет, что типа вот, опыт показывает, что нехорошо выходит с unsigned-то. В целом более или менее убедительно.


Тем не менее, комитет по стандартизации языка С++ решил, что активное использование беззнаковых типов в STL приемлемо. Там, наверное, одни "Тарасевичи" сидят...

E>А что же говорит нам уважаемый Андрей?

E>Что unsigned индексы массивов таки понятнее?

Разумеется. Кстати, никак не противоречит Страуструпу.

E>Что unsigned таки гарантирует беззнаковость значения?


Разумеется. А это откуда взялось? Что, кто-то говорит, что не гарантирует? Страуструп, может быть?

E>Что переполнения не избежать по любому, так что всё время надо писать код, который корректно работает в условиях переполнения и всюду на него закладываться?


Передернуто. Не "переполнения не избежать", а "опасности переполнения не избежать". Кстати, опять никак не противоречит Страуструпу.

E>или я что-то таки недопонял?


А Вы и не пытаетесь понять. Вы занимаетесь флеймом. Многим это было очевидно и раньше, но сейчас это уже, я уверен, очевидно всем.

Мне, например, было соврешено очевидно, что ответ от Erop мое последнее сообщение будет написан на тему "Тарасевич vs Страуструп".

E>но старик-то Срауструп может заслужил аргументированых возражений на свои соображения,


Возражений тут целая дискуссия. Зачем повторять их снова?

E>или это он всё писал для секретарш иногда применяющих С++ для своих нужд, а не для сверхкрутых перцев с КЫВТ/С++?


Ну если дла Вас мир делится только на "секретарш" и "сверхкрутых перцев", то, как говорится, ту уж ничего не попишешь...
Best regards,
Андрей Тарасевич
Re[22]: Давай немного подробнее?
От: Erlond Россия  
Дата: 18.11.06 11:06
Оценка: 6 (1)
Прошу прощения за фразу "Вот смотрю и вижу, что ты пытаешься писать код для беззнаковых чисел, как будто они знаковые, конечно такое работать не будет."
Re[25]: Ещё раз о галвном :)
От: dr.Chaos Россия Украшения HandMade
Дата: 14.12.06 12:20
Оценка: 6 (1)
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, dr.Chaos, Вы писали:


DC>>По поводу хранения величин по смыслу unsigned в signed, это правда толком ничего не дает, хотя я думаю это стоит отнести к вопросам стиля. А все вопросы связанные со стилем это уже СВ .

DC>>Но полагаю, что при использовании unsigned все таки нет UB, т.к. он одинаково представляется на всех платформах. Да и он правда заставляет быть более внимательным.

E>Ну собственно мой взгляд такой. Пока ван не нужны операции сдвига, деления и взятия остатка с участием отрицательных чисел, то вам signed ничем не мешает, а unsigned не даёт никаких преимуществ.


Да я понял твой взгляд, я все обсуждение прочел.

DC>>Можно провести аналогию с исключениями, т.к. они требуют значительно больше внимания чем коды возврата, но и дают тоже больше гарантий.


E>Ну вот, ИМХО, эта анология ложная, так как unsigned не то что дают какие-то гарантии, а наоборот, в тех случаях, когда у signed возможны проблемы, гарантирует проблемы в любом случае, при преобразованиях между signed и unsigned арифметикой


Я согласен что преимуществ значительно меньше, но они таки есть. Для хранения в беззнаковом их действительно почти нет, но для индексов и размеров массивов, это разумно.

Портируемость С++ ты видимо не верно понимаешь . Она говорит о том что стандартная библиотека будет работать на разных платформах одинаково, а то что ты написал, это уж извини как написал так и работает .

Использование беззнаковых делает человека более внимательным, а это уже плюс.
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Re[6]: Всё очень просто....
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 20:20
Оценка: 4 (1)
Здравствуйте, MaximE, Вы писали:

ME>Забавно, что без unsigned невозможно хранить в однобитовом члене 1. С signed

ME>только -1 и 0.

Строго говоря, и в С и в С++ битовое поле, объявленное с типом просто 'int' может быть как signed, так и unsigned. Это implementation defined. Чтобы везде было именно signed, надо явно писать 'signed int'. Это, кажется, единственное место в С/С++, где просто 'int' может быть синонимом для 'unsigned int'.
Best regards,
Андрей Тарасевич
Re[7]: Нужен ли unsigned
От: night beast СССР  
Дата: 13.11.06 09:35
Оценка: 1 (1)
Здравствуйте, johny5, Вы писали:

АТ>>int a[N];
АТ>>int* p = a + N;

АТ>>while (--p >= a)
АТ>>  *p = 0;


АТ>>Типичный 'int'-овый программист зачатсую даже и не видит проблемы в этом коде. Более того, такой код зачастую "работает". В то время как на самом


J>Что то я действительно не вижу проблем в таком коде...


если не ошибаюсь, сравнение с указателем который указывает не на "элемент массива или элемент после конечного" -- UB.

зачем так мне не известно.
Re[10]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 19:28
Оценка: 1 (1)
Здравствуйте, Erop, Вы писали:

E>Я не согласен, что atoi устарела больше, чем scanf, уважаемый эксперт Андрей


Хм... Ты, по-видимому, невнимательно читаешь. Не в первый раз уже. Я никогда не утверждал, что "atoi устарела больше, чем scanf" (чем scanf??? ). Я утверждал, что 'atoi' устарела больше, чем 'strtol', если уж пользоваться не совсем подходящим в данном случае словом "устарела"...

E>Мало того, твои аргументы меня так и не убедили


"Не убедили"? Здесь не ромашка — убедили/не убедили. Аргументы против 'atoi' — формально строгие. Другими словами, бесполезность 'atoi' (и 'sscanf') для решения такой задачи в общем случае фактически констатируется стандартом языка. Так что никакого убедили/не убедили тут быть не может. Если у тебя есть какие-то фактические контраргументы — милости просим их сюда... А нет — значит вопрос решен.

E>Тем не менее, часто довольно бывает так, что лексический анализ текстового потока происходит в одном месте, а преобразование чисел представленных строками в числовое представление в другом


Во-первых, "лексический анализ потока" (за исключением совсем уже вырожденных случаев) не позволяет определить принадлежности представленного числа целевому диапазону — именно это является основной проблемой 'atoi'. (Я подозреваю, что для спасения 'atoi' в рамках это дискуссии найдутся люди, которые бы с удовольствием реализовали "лексический анализ потока", который будет принимать 32767 и отвергать 32768 не используя функций первода, но тем не менее ценность такой "лексический анализ" будет представлять не более чем юмористическую )

Во-вторых, функция 'atoi' сама по себе содержит внутри себя некий недоступный снаружи "лескический анализ". Попытка ручного "воспроизведения" такого анализа где-либо еще в коде — кривой и потенциально гемморойный подход, приемлемый только в вынужденнных случях. В разумной реализации как на этапе "лексического анализа", так и в процессе конверсии строки в число, должен работать один и тот же анализатор. Как раз таки функции типа 'strtol' и предосталяют такую возможность, пусть в ограниченной сепени.
Best regards,
Андрей Тарасевич
Re[13]: Спрашиваю исключительно из интереса
От: Roman Odaisky Украина  
Дата: 14.11.06 21:15
Оценка: 1 (1)
Здравствуйте, Erop, Вы писали:

E>3) Как быть без итераторов?

E>Собственно я вот отказался от использования STL и его представления об итераторах и не жалею нисколько. И как-то пока ни разу не хотелось вернуться
E>Я даже не против идеи итератора как такового. Только итераторы надо рожать там, где они действительно нужны, а не всюду и всегда ?)
E>Просто мне кажется, что для доступа к массиву намного удобнее индекс

А я привык к указателям/итераторам, они мне импонируют больше.

E>А вообще итератор чего-то, как идея, не всегда плох. Хотя то, что ты назвал енумератором, обычно проще в реализации и не сложнее в использовании


Спрашиваю исключительно из интереса: что есть реально рабочее, умеющее красиво перебирать элементы коллекций, позволяющее писать абстрактные алгоритмы, легковесное? Вот ты какими неитераторами пользуешься?

E>Мне особенно не нравятся итераторы из STL потому что они копируют зачем-то семантику указателей.

E>Вроде как все попробовали и осознали, что писать на голых указателях стрёмно. и не только потому, что не безопасно, но и потому, что непонятно
E>На кой нарожали три мешка шаблонов, чтобы доступ к довольно высокоуровневым коллекциям, загнуть в такую же уродскую парадигму -- я лисно понять совершенно не могу

maybe.
До последнего не верил в пирамиду Лебедева.
Re[10]: Эх, товарищ, товарищ...
От: remark Россия http://www.1024cores.net/
Дата: 15.11.06 05:21
Оценка: 1 (1)
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Используя беззнаковый тип я средствами языка передал читателю (и компилятору) информацию о том, что даннная величина не имеет осмысленных отрицательных значений


Извините, что вмешиваюсь

Проблема в том, что до компилятора С++ это очень плохо доходит (именно в плане знаковых/беззнаковых):

int f1(int)
{
    return -1;
}

unsigned f2(unsigned)
{
    int i = -1;
    return i;
}

unsigned f3(unsigned i, unsigned i2)
{
    return i - i2;
}

int main()
{
    int i = -1;

    f1(i);
    f2(i);
    f3(1, 2);
}


msvc71 /w4 — ни одного варнинга!

И проблему усугубляет ещё то, что ведь а программист теперь-то надеется на компилятор. А куда без этого? С современными программами и темпами разработки без помощи компилятора не обойтись.
Аргументы "кривые руки" мне кажутся не совсем жизненными. По крайней мере ни одного программиста с прямыми руками я ещё не видел, и не слышал о таком.

Касательно других типов до компилятора доходит значительно лучше. Вот, например, программист повысил читабельность и сообщил компилятору, что функция возвращает только true/false (promoted to 0/1). Соответственно в такой программе получаем ожидаемый варнинг:

bool f5();

int main()
{
    if (-1 == f5());
}



Например, когда я пытаюсь передать std::string как парметр int, совершенно логично программа не скомпилируется.
Фактически программист хочет ожидать, что в приведённом примере не скомпилируется вызов f2. А почему нет? Разьве это не разные типы?
Так же хотелось бы ожидать, что не скомпилируется и функция f3. По-моему это логично. Когда мы из одного числа вычитаем другое какой тип у нас получается? unsigned? Ну вообще-то по всем законам здравого смысла вроде как должен получится signed. Но в С++ почему-то не так.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: Мои извращённые желания
От: johny5 Новая Зеландия
Дата: 18.11.06 02:22
Оценка: 1 (1)
Ребят, вы уже сделайте safe_unsigned класс, который при операции вычитания возвращает int.
А на всякие неявные преобразования safe_unsigned <-> int выдавал бы компилер еррор.

И будет вам счастье.
Re: Нужен ли unsigned
От: Sinclair Россия https://github.com/evilguest/
Дата: 26.04.07 11:29
Оценка: 1 (1)
Здравствуйте, <Аноним>, Вы писали:

По этому поводу я думаю, что:
а) понятно, что все проблемы возникают от того, что арифметика с конечной разрядностью существенно отличается от школьльной. При этом, в общем-то, unsigned и signed примерно одинаково плохи.
б) просто unsigned придвигает опасную границу близко к привычным нам числам. Если "три миллиарда" встречаются в основном в архиваторах и прочих софтах, работающих с массивами данных, то 0+- лапоть у нас на каждом шагу.
в) язык программирования должен помогать программистам, а не мешать им.
г) вполне неплохим решением могла бы быть полноценная поддержка в арифметике чисел с бесконечной разрядностью.
д) Интуитивно ясно, что это бы привело к проблемам с производительностью. Хотя я в этом вовсе не уверен. Разве нельзя делать операцию сложения полиморфной, и автоматически переключаться в нужную разрядность как только произошло целое переполнение? Вполне может оказаться, что производительность этого дела на современных CPU устроит всех потребителей. Надо ковыряться в деталях, смотреть на конкретный asm-код и особенности работы предсказателя переходов.
е) Другой альтернативой является checked арифметика, где после каждой операции проверяется бит переполнения. Штука тоже дорогая, но может оказаться дешевле, чем то же самое, но написанное вручную.
Потому, как если вы собрались даже посчитать среднее от двух чисел, неважно, знаковых там или беззнаковых, то банальное (a + b) / 2 не проконает. Нужно
— или обкладывать параметры проверкой на переполнение
— или расширять до следующей разрядности (что не всегда возможно)
— или ловить переполнение постфактум и выполнять дополнительные приседания.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Нужен ли unsigned
От: Аноним  
Дата: 12.11.06 13:13
Оценка: :)
Я решил попробовать писать "правильный" код. Для ширины например — unsigned, т.е. она не бывает отрицательной. И тд.
Но как меня всякие мелочи задолбали, извините. Чуть чуть перепутал, и всё, 4 миллиарда, вся логика валится.
Если int-ы хоть можно проверить на -1, то unsigned-ы как проверишь? Непонятно.
Собственно вопрос, оправдан ли такой геморрой? Или сделать :%s/unsigned/int/g и жить счастливой жизнью?
С одной стороны вроде бы unsigned идеологически лучше. Но с другой, не получается у меня нормально с ними писать. Каждый раз, когда фунцию с аргументом типа unsigned вызываешь, надо проверять, не передастся ли туда отрицательное число, а если бы она была int, то проверку можно было бы сделать внутри функции (ну не писать же
void f(unsigned x)
{
    if ((int)x < 0) // something bad
}
)
Что вы думаете по этому поводу?

18.04.07 14:44: Перенесено модератором из 'C/C++' — Кодт
Re: Нужен ли unsigned
От: Centaur Россия  
Дата: 12.11.06 14:21
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Я решил попробовать писать "правильный" код. Для ширины например — unsigned, т.е. она не бывает отрицательной. И тд.

А>Но как меня всякие мелочи задолбали, извините. Чуть чуть перепутал, и всё, 4 миллиарда, вся логика валится.

Нужно обращать внимание на warning’и компилятора. И иметь компилятор, который их сыплет по всякому поводу.
Re[3]: Нужен ли unsigned
От: FDSC Россия consp11.github.io блог
Дата: 12.11.06 14:42
Оценка: :)
Здравствуйте, Аноним, Вы писали:

А>gcc, -Wall -Wextra

А>варнингов нет. Да и откуда ему знать, что получится при m_width — m_pageWidth: 10 или 0 или -10

А кто мешает проверить ПЕРЕД операцией?
Re[3]: Нужен ли unsigned
От: Michael7 Россия  
Дата: 12.11.06 16:49
Оценка: :)
Здравствуйте, Аноним, Вы писали:

А>gcc, -Wall -Wextra

А>варнингов нет.

Вы добавьте -ansi -pedantic Может появятся

А> Да и откуда ему знать, что получится при m_width — m_pageWidth: 10 или 0 или -10


К сожалению, gcc не выдаёт предупреждений, но в принципе компилятор c/c++ мог бы выдавать предупреждения, если результат вычитания присваивается беззнаковой переменной.
Re: Нужен ли unsigned
От: johny5 Новая Зеландия
Дата: 13.11.06 09:18
Оценка: :)
Вместо
void f(int i)
{
  if(i < 0 || i >= cont.size())
     return;
}


можно писать
void f(unsigned i)
{
  if(i >= cont.size())
     return;
}


т.е. сократить одно условие
Re[2]: Нужен ли unsigned
От: Шахтер Интернет  
Дата: 13.11.06 10:13
Оценка: :)
Здравствуйте, Michael7, Вы писали:

M>Здравствуйте, Аноним, Вы писали:


А>>Я решил попробовать писать "правильный" код. Для ширины например — unsigned, т.е. она не бывает


M>А я наоборот, полагаю, что unsigned, по возможности, надо объявлять только в редких случаях и только для неарифметических по смыслу переменных. То есть таких, над которыми никогда не проводятся арифметические операции. И даже для них, если нет нужды не надо unsigned, так я почти никогда не объявляю unsigned даже индексные переменные.


Очень плохо.

M>Иначе чревато трудно обнаружимыми ошибками в промежуточных вычислениях.


void func(char *p,size_t s)
 {
  for(int i=0; i<s ;i++) p[i]=0;
 }


Надо обьяснять, где здесь ошибка?
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[3]: Всё очень просто....
От: Erop Россия  
Дата: 13.11.06 11:50
Оценка: +1
Здравствуйте, Шахтер, Вы писали:

E>>signed -- для чисел

E>>unsigned -- для флажков.
Ш>По-моему, это та простота, которая хуже воровства.

Ну прости, я ответил на вопрос, что же я таки думаю.
ИМХО выгоды от использования беззанковых чисел всегда какие-то призрачные.
Конечно есть какие-то специальные очень случаи, когда хочется именно беззнакового и именно 32-ного числа.

Но, это очень большая редкость. Я вот припоминаю только один случай.

Обычно беззнаковые числа хочется использовать для каких-то объектов, которые числами не являютчся (скажем над ними не производят арифметических действий, например).
Это или какие-то ID или сборки флагов или ещё какие-нибудь хитрые конструкции. но никак не результат сложения/вычитания/деления/умножения/взятия остатка.

пример о котором я помню -- млпдшее слово в руками сделанном двухсловном числе.

Кроме того беззнаковость числа ничего хорошего ни в CT ни в RT не гарантирует.
Ну а выгоды я хотел бы узнать (кроме, конечно, выгоды в один бит)

Часто выгода в один бит всё равно бесполезна. Ну и потом обычно это всё непереносимо
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Нужен ли unsigned
От: last_hardcoder  
Дата: 13.11.06 12:11
Оценка: +1
Здравствуйте, Аноним,

Беззнаковые типы не то чтобы не нужны. Однако использовать их для представления ширины или ещё чего-то заведомо положительного нет смысла. Предположим, нам надо сохранить не саму ширину, а разницу между шириной одного и другого окна. Она может быть как положительной, так и отрицательной.
Re[6]: А может проще таки быть проще? :)
От: Erop Россия  
Дата: 13.11.06 16:05
Оценка: +1
Здравствуйте, Андрей Тарасевич, Вы писали:
АТ><...>

АТ>Правильная реализация такого цикла


АТ>
АТ>int a[N];
АТ>int* p = a + N;

АТ>while (p > a)
АТ>  *--p = 0;
АТ>


АТ>является одним из варинатов "шаблонного" решения, применимого и к примеру с unsigned циклом


АТ>
АТ>unsigned someCounter = 99;
АТ>while(someCounter > 0) {
АТ>  --someCounter
АТ>  ...
АТ>}
АТ>


АТ>Я могу лишь посторить, что специфика "близости края интервала", присущая беззнаковым типам и за которую их часто "не любят", в языках С и С++ присуща далеко не только беззнаковым типам. Если внимательно поискать, найти ее можно практически везде. И спрятаться от нее вам не удастся, как бы вы этого не хотели.


А может писать как-то попроще. Скажем так:

int a[N];
for( int i = N - 1; i >= 0; i-- ) {
    a[i] = 0;
}


Компиляторы у нас сейчас хорошие, оптимизирующие. Код вроде как тоже понятный
Ну а то, что так нельзя с итераторами программировать, так, ИМХО, это проблема дизайна итераторов, а не необходимости пользоваться всюду ьеззнаковыми типами
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Решите тогда задачу
От: Roman Odaisky Украина  
Дата: 13.11.06 16:44
Оценка: +1
Хорошо, а как «правильно» решить следующую простейшую задачу?

Круг разбит на n > 0 секторов, пронумерованых подряд числами 0, 1, ..., n – 1. Некто стоит в секторе номер 0, затем идет по кругу, делая s шагов. Куда он попадет?

Пример:
nsРезультат
3
3
3
3

3
3
3
3

3
999
4294967295
0
1
2
3

4
-1
-2
-3
-4
-2147483648
-2147483648
0
1
2
0

1
2
1
0

2
718
2147483647
unsigned f(unsigned n, int s)
{
    . . . ?
}
До последнего не верил в пирамиду Лебедева.
Re[5]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 13.11.06 17:35
Оценка: :)
Здравствуйте, Кодт, Вы писали:

К><>

АТ>>Я не знаком ни с какими "потенциальными проблемами" беззнаковых типов. В моем коде, например, практически все целочисленные типы — беззнаковые, за исключением случаев, когда действительно приходится работать со знаковой величиной.
К><>

К>Не столько проблема, сколько неудобство (иногда).

К>В знаковой арифметике одно и то же неравенство можно выразить несколькими способами: x<y, x-y<0, 0<y-x, а в беззнаковой — единственным x<y. А если слева и справа — по нескольку слагаемых/вычитаемых, то рукодельная нормализация приводит к плохо читаемому коду.

Способ 'x-y' в общем случае так же неприменим к знаковым типам, как непирименим к беззнаковым.

Отдельно, кстати, стоит заметить, что, несмотря на то, что большая часть машинных арифметических операций на популярных арихитектурах не требуют различения знаковых и беззнаковых типов, такие требования языков С/С++, как округление у нулю при целочисленном делении, зачастую таки приводят к генерации менее эффективного кода для знаковых типов. Для беззнакового типа, например, деление на 2 эквивалентно сдвигу на 1 бит вправо, а вот со знаковым типом в дополнительном коде приходится возиться дополнительно.
Best regards,
Андрей Тарасевич
Re[2]: Решите тогда задачу
От: Андрей Тарасевич Беларусь  
Дата: 13.11.06 18:18
Оценка: :)
Здравствуйте, Roman Odaisky, Вы писали:

RO>Хорошо, а как «правильно» решить следующую простейшую задачу?


RO>Круг разбит на n > 0 секторов, пронумерованых подряд числами 0, 1, ..., n – 1. Некто стоит в секторе номер 0, затем идет по кругу, делая s шагов. Куда он попадет?


Так а что означают этти загадочные числа "с потолка" в конце таблицы? Это при том-то, что реализации функции не приведено
Best regards,
Андрей Тарасевич
Re[3]: Решите тогда задачу
От: Андрей Тарасевич Беларусь  
Дата: 13.11.06 18:28
Оценка: :)
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Здравствуйте, Roman Odaisky, Вы писали:


RO>>Хорошо, а как «правильно» решить следующую простейшую задачу?


RO>>Круг разбит на n > 0 секторов, пронумерованых подряд числами 0, 1, ..., n – 1. Некто стоит в секторе номер 0, затем идет по кругу, делая s шагов. Куда он попадет?


АТ>Так а что означают эти загадочные числа "с потолка" в конце таблицы? Это при том-то, что реализации функции не приведено


А, понял. Это правильные результаты, а не "с потолка"...

И все таки интересно, какую связь этой задачи с данной дискуссией видит автор?
Best regards,
Андрей Тарасевич
Re[2]: Нужен ли unsigned
От: Michael7 Россия  
Дата: 13.11.06 20:07
Оценка: +1
Здравствуйте, Шахтер, Вы писали:


Ш>1) Беззнаковая арифметика имеет точно определённую семантику, в отличии от знаковой.


Вы не могли бы пояснить, потому что мне представляется, что это архитектурно зависимо.

Ш>2) В беззнаковой арифметике лего ловить переполнение.


Ш>
Ш>unsigned a=...;   
Ш>unsigned b=...;

Ш>a+=b;

Ш>if( a<b ) 
Ш>  { //overflow  
Ш>   ... 
Ш>  }
Ш>


Код изящен и эффективен, но думаю может привести к неприятным трудноуловимым ошибкам. В стандарте C99 результат целочисленного переполнения UB, как в C++2003 стандарте менее ясно, там как-то закручено по-моему.
По-моему, очевидно и то, что результат может зависеть как от архитектуры компьютера, так и даже от компилятора и остального кода. Даже в случае x86 процессора после переполнения выставляется флаг C (carry flag) и нет никакой уверенности в том, как он используется остальным сгенерированным кодом. Признаться я не знаю примера, когда подобный код привёл бы к ошибке, но чисто теоретически полагаю его небезопасным.

Ш>3) В C/C++ размерности массивов выражаются беззнаковым типом size_t. По этой причине ипользовать для индексирования знаковые типы -- создавать потенциальные дыры.


В этом случае может быть. Если очень большие массивы.

Ш>4) LUT удобнее делать с беззнаковыми типами. Классический пример.


Ш>
Ш>bool CharIsXXX(char c)
Ш> {
Ш>  static const bool table[256]={...};

Ш>  return table[(unsigned char)c];
Ш> }

Ш>


Ну так и я не противлюсь везде и всюду беззнаковым типам. Иногда они к месту, как здесь. Но не для случаев, когда просто некая вычисляемая сущность не может быть отрицательной.
Re[4]: Нужно искать внимательнее, товарищ эксперт!
От: Erop Россия  
Дата: 14.11.06 09:33
Оценка: :)
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Конечно, лучше! Вот только где бы найти такой оптимизатор... Т.е. ясно, что нет такого оптимизатора и быть не может, но все равно — лучше бы он...


А какие проблемы с принципиальным существованием такого оптимизатора?

Ведь в коде


int i;
int size;
assert( 0 <= size );

if( 0 <= i && i < size ) {
    Do1();
}

if( unsigned( i ) < unsigned( size ) ) {
    Do2();
}


Do1() и Do2() будут всегда вызываться одновременно.
Так что условия в if'ах совершенно эквивалентны. только перове условие понятнее.

при этом оптимизатор занет переносима такая оптимизация или нет
О том, что в большинстве случаев это будет ещё и преждевременная оптимизация я скромно стараюсь не вспоминать
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[11]: Не! проще таки лучше!
От: Roman Odaisky Украина  
Дата: 14.11.06 11:09
Оценка: :)
Здравствуйте, Erop, Вы писали:

E>Ну а с тем, что "эти абстракции" зарыты намного глубже я тоже совершенно согласен.

E>про то и вопрос. От чего в языке фортран или там паскаль массивы было удобно итерировать знаковым индексом, а в C++ + STL стало так трудно и опасно?

Желающие могут попробовать:
var a: array[-1..1] of whatever;
. . .
a[-2] = 0;

много счастья будет?

E>Да, от чего вообще в этом обсуждении возник STL.

E>Собственно ты сам начал проводить аналогии между unsigned индексом и STL-ными итераторами.
E>Действительно и там и там нельзя сделать "лишний шаг"
E>А в знаковом индексе -- можно.

Здесь очень как-то однобоко можно.
int i = . . .;
if(i >= 0)
{
    a[i] = 123; // ладно, так можно...
}

T* p = . . .;
if(p >= first) // Всем искренне желаю, чтоб это всегда выполнялось.
{              // Ибо иначе UB. Причем есть вполне реальная угроза аппаратного исключения
    *p = 123;  // при загрузке в регистр сомнительного указателя (вдруг массив попал в самое начало странички).
}              // Или ОС обругает за выход за границу дозволенной памяти (хотя это тоже маловероятно).


E>После этого ты стал утверждать, что раз уж в STL-way (через указатели и итераторы) итерации лишний шаг делать нельзя, то не надо приучаться к такой возможности при итерации через индекс.


Так это и C++ way, в том-то и дело. Добрый дед Ю. Би с топором.

E>А я во делаю совершенно противоположенный вывод. Раз уж в STL-way делать "лишний шаг" опасно, а часто хочется, то это косяк STL-way.


И опять же. (new X[N]) – 1 — UB. Это вопрос уже к языку. И я бы посмотрел на «правильную» семантику --someDeque.begin(). Или ты считаешь итераторы ошибкой? Может быть. Только что тогда вместо них? Enumerators вряд ли решают эту проблему.

E>Мне кажется, что лучше избегать STL-way итерации.


тот же вопрос... как тогда?

E>Забавно, кстати, что сами авторы STL пожоже это тоже чувствовали. Потому что понаписали всяких for_each


Может, и чувствовали... но вроде есть и более другие поводы для существования for_each.

E>В принципе я их понимаю. Так как простой for() при использовании итераторов и unsigned индексов действительно становится неудобным и опасным


А вот с этим согласен. Бывает. Иногда хочется примерно так:
for(int i = 0; i < n; i += k)
{
    . . . a[i] . . .
}

с итераторами это хоть и можно, но сложнее, придется какой-то свой skip_iterator соображать.
До последнего не верил в пирамиду Лебедева.
Re[4]: Где тут ошибка
От: Шахтер Интернет  
Дата: 14.11.06 14:33
Оценка: :)
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Шахтер, Вы писали:


Ш>>
Ш>>void func(char *p,size_t s)
Ш>> {
Ш>>  for(int i=0; i<s ;i++) p[i]=0;
Ш>> }
Ш>>


Ш>>Надо обьяснять, где здесь ошибка?


E>Зачем объяснять?


Действительно незачем. Ответ очевидный.

E>Ошибка в том, что s имеет беззнаковый тип.


Неверно. Очевидно, ответ очевиден не для всех.

E>Она же допущена и в std::vector


См. выше.

E>Ну и что?


А то что без беззнаковых типов невозможно писать надежный и переносимый код в этом и во многих других случаях.

E>1) реально size таким большим не бывает, так как в память плохо помещается


Неверно. На Win32 -- если система загружена с опцией 3GB. На Win64 вообще int 32 разрядный а size_t 64.

E>2) Лично я и std::vector не пользуюсь. Пользуюсь массивами из другой библиотеки, там размер массива int


Да ради бога.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[7]: Нужен ли unsigned
От: Шахтер Интернет  
Дата: 14.11.06 14:59
Оценка: :)
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Шахтер, Вы писали:


К>>>В знаковой арифметике одно и то же неравенство можно выразить несколькими способами: x<y, x-y<0, 0<y-x, а в


Ш>>В знаковой арифметике эти выражения точно так же не эквивалетны. Кроме того, x<0 не эквивалетно -x>0.


К>Ну не "точно так же".


Именно точно так же. Знаковые x и y или беззнаковые x-y<0 НЕ эквивалентно x<y.

К>Конечно, в области больших чисел есть риск поймать переполнение.

К>Но предусловие "оба числа по абсолютному значению не превосходят MAXINT/2" достаточно распространено, и этим можно пользоваться.

Я честно не понимаю, если нужно узнать, что больше x или y, то зачем писать

x-y<0 вместо x<y ? Зачем искуственно сужать область правильной работы функции?

К>Кстати говоря. Это и плюс, и минус одновременно. С одной стороны, упрощаются выражения, а с другой — есть риск забыть проверки и получить феерверк на больших значениях. Беззнаковая же арифметика не прощает халатности с самого начала.


Я бы всё-таки хотел более конкретных примеров, как упрощаются выражения.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: Нужен ли unsigned
От: Шахтер Интернет  
Дата: 14.11.06 16:01
Оценка: +1
Здравствуйте, last_hardcoder, Вы писали:

_>Здравствуйте, Аноним,


_>Беззнаковые типы не то чтобы не нужны. Однако использовать их для представления ширины или ещё чего-то заведомо положительного нет смысла. Предположим, нам надо сохранить не саму ширину, а разницу между шириной одного и другого окна. Она может быть как положительной, так и отрицательной.


Я совершенно согласен, что в оконном менеджменте нет большого смысла использовать беззнаковые числа. Вопрос об использовании знаковой или беззнаковой арифметики должен решаться исходя из существа задачи.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[5]: Нужно искать внимательнее, товарищ эксперт!
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 18:07
Оценка: :)
Здравствуйте, Erop, Вы писали:

АТ>>Конечно, лучше! Вот только где бы найти такой оптимизатор... Т.е. ясно, что нет такого оптимизатора и быть не может, но все равно — лучше бы он...


E>А какие проблемы с принципиальным существованием такого оптимизатора?


Соврешенно очевидные — в общем случае невозможно гарантирвать, что знековая переменная никогда не принимает отриуательных значений. Следовательно удалить проверку на отрицательность оптимизатор не сможет.

E>Ведь в коде

E>
E>int i;
E>int size;
E>assert( 0 <= size );

E>if( 0 <= i && i < size ) {
E>    Do1();
E>}

E>if( unsigned( i ) < unsigned( size ) ) {
E>    Do2();
E>}
E>


E>Do1() и Do2() будут всегда вызываться одновременно.

E>Так что условия в if'ах совершенно эквивалентны.

Ну зачем же пытаться запутать участников дискуссии очевидно неверными утверждениями? Оба утверждения неверны и контрпример очевиден. Компилятор не имеет ни малейшего представления о реальном диапазоне значений 'i' и, соотвественно, не может быть уверен в том, что 'unsigned( i )' для отрицательных 'i' окажется заведомо больше 'unsigned( size )'. Поэтоум ожидать, что оптимизатор сумеет свести первое ко второму не приходится.

E>только первое условие понятнее.


В таком странном виде — разумеется. А вот если написать правильно — т.е. использовать беззнаковые объекты, то именно второй вариант будет понятнее. Причем понятнее стантет не только условие, понятнее станет вся программа, ибо уже из декларации значений станиет ясно, что они не могут быть отрицательными. В случае же со знаковой декларацией придется рыться в коде, для того, чтобы выяснить этот простой факт.

E>О том, что в большинстве случаев это будет ещё и преждевременная оптимизация я скромно стараюсь не вспоминать


Есть такая полушутливая пословица "Если программа работает правильно, то это значит, что в ней содержится четное число ошибок". Вот этот пример кода выше — это как раз пример такой программы. Сначала был сделан ошибочный выбор в пользу знакового типа, а затем, чтобы "скомпенсировать" это ошибку, была добавлена еще одна — проверка значения [положительной по сути] знаковой переменной на отрицательность. В результате программа "работает".

А я вот предпочитаю не делать первой ошибки вообще. Тогда и не надо будет вставлять в программу и "компенсаторы" этой ошибки. Ону просто будут не нужны. Удаление из кода соврешенно не нужных проверок, зачем-то туда засунутых — это не оптимизация, это банальное восттановление удобочитаемости и элегантности кода.
Best regards,
Андрей Тарасевич
Re[9]: Где тут ошибка
От: Erop Россия  
Дата: 14.11.06 18:11
Оценка: +1
Здравствуйте, Андрей Тарасевич, Вы писали:

E>>Нет уж. Числа лучше бы использовать нормальные.

E>>И отлаживать проще и программировать и всё такое.

АТ>Не вижу в этом сообщении содержания. Соответственноо и ответить ничего содержательного не могу.


А писл-то зачем?


Видимо это была завуалированная просьба пояснить. Вот, пытаюсь:

Смотри, тебе уже тут наприводили вагон примеров.
Вот есть у тебя числовая величина. Скажем число деталей, которые произвёл сотрудник за месяц.
И не может эта штука быть отрицательной.

но потом, когда ты с нею начинаешь работать, выяснятеся, что появляются у тебя разности в программе. Ну типа там "на сколько Вася произвёл больше, чем Петя?". Или "на сколько больше деталлей произвёл в этом месяце Вася, чем в прошлом". И даже такой вот вопрос: "Когда рост числа произведённых Васей за месяц деталлей был больше, зимой или летом?"

А вдруг Вася разгильдяй. И иногда этот "рост" оказывается отрицательным?
Конечно можно напрячься, перенсти все члены во всех неравенствах в нужные стороны. Преобразовать все выражения как-то хитро и таки родить это всё на беззнаковой арифметике теки можно. не вопрос. толку-то только чуть. С простыми числами из математики так сказать проще.
Ну возникают отрицательные числа при работе с числовыми величинами естественным образм. Ну что с простым мат. фактом-то спорить?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Нужен ли unsigned
От: Lepsik Индия figvam.ca
Дата: 14.11.06 18:18
Оценка: :)
это просто разные типы данных. В одном случае знаковый 7-битный, в другом 8-битный.

Без второго большая часть известных библиотек практически нереализуема. Конкретный пример — нет ни одной ОС написанной на языках без безнаковых типов
Re[7]: Нужен ли unsigned
От: MaximE Великобритания  
Дата: 14.11.06 18:32
Оценка: +1
Андрей Тарасевич wrote:

> Неверно. 'atoi' и иже с ними — функции "мертвые" и практической ценности

> не представляющие. Немножко "живее" — 'sscanf', который поддерживает
> unsigned, но и тот, к сожалению, неполноценен. Настоящие функции
> преобразования строк к целым из библиотеки С — 'strtol' и 'strtoul'
> (плюс 'll' версии в С99), из которых последняя как раз unsigned.

Чем sscanf неполноценен?

По крайней мере в gnu libc, sscanf использует strtoul(l). Было бы удивительно,
если бы другие реализации так же не поступали — обыкновенный code reuse.

http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/stdio-common/vfscanf.c?rev=1.115&amp;content-type=text/x-cvsweb-markup&amp;cvsroot=glibc

--
Maxim Yegorushkin

No Microsoft product was used in any way to write or send this text.
If you use a Microsoft product to read it, you're doing so at your own risk
Posted via RSDN NNTP Server 2.0
Re[10]: Где тут ошибка
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 18:46
Оценка: +1
Здравствуйте, Erop, Вы писали:

E>Смотри, тебе уже тут наприводили вагон примеров.

E>Вот есть у тебя числовая величина. Скажем число деталей, которые произвёл сотрудник за месяц.
E>И не может эта штука быть отрицательной.

E>но потом, когда ты с нею начинаешь работать, выяснятеся, что появляются у тебя разности в программе. Ну типа там "на сколько Вася произвёл больше, чем Петя?". Или "на сколько больше деталлей произвёл в этом месяце Вася, чем в прошлом". И даже такой вот вопрос: "Когда рост числа произведённых Васей за месяц деталлей был больше, зимой или летом?"


E>А вдруг Вася разгильдяй. И иногда этот "рост" оказывается отрицательным?

E>Конечно можно напрячься, перенсти все члены во всех неравенствах в нужные стороны. Преобразовать все выражения как-то хитро и таки родить это всё на беззнаковой арифметике теки можно. не вопрос. толку-то только чуть. С простыми числами из математики так сказать проще.
E>Ну возникают отрицательные числа при работе с числовыми величинами естественным образм. Ну что с простым мат. фактом-то спорить?

Стоп, стоп, стоп... Ты, по моему, пытаешья запутать участников дискуссии.

Никто пока не утверждлал, что при работе с беззнаковыми величинами не может возникнуть отрицательных значений. Откуда ты это взял? Все, что пока утверждалось, предельно просто: если значение является положительным, то для его представления используется беззнаковый тип, а если значение может быть отрицательным, то для его представления используется знаковый тип. Тут все просто.

Итак, количество произведенных деталей отрицательным быть не может. Никаким естественным образом. Соответственно, для представления этих значений используется беззнаковый тип. Ранее ты утверждал, что эта величина для каких-то утилитарных целей (примеры с циклом и т.п.) должна иметь возможность принимать отрицательные значения. Теперь ты вдруг втихаря "перевел стрелки" с этой величины на совершенно и принципиально другую — разность между двумя такими значениями — и недеешся, что никто не заметит подмены? Сорри, это уже совсем другая песня.

Может ли быть дельта между значениями отрицательной — это вопрос постановки задачи. Согласно сделанной тобой постановке, эта величина может быть отрицательной. Прекрасно — это означает, что даннная величина будет представлена знаковым значением.

Вот и все.

Я подозреваю, что следующим шагом будет попытка убедить меня в том, что "очень легко ошибиться" при вычитании первого из второго, т.е. забыть перевести вычисления в рамки знаковых типов. Над подобными аргументами можно только посмеяться.
Best regards,
Андрей Тарасевич
Re[11]: А ради чего таки все эти усилия? :)
От: Erop Россия  
Дата: 14.11.06 19:35
Оценка: -1
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Я подозреваю, что следующим шагом будет попытка убедить меня в том, что "очень легко ошибиться" при вычитании первого из второго, т.е. забыть перевести вычисления в рамки знаковых типов. Над подобными аргументами можно только посмеяться.


А почему?

Вот вроде как естественная нужда, сравнить у кого в апреле был прирост производительности больше и Васи или у Пети.
Вот какая будет реализация в случае последовательно знаковых типов и какая в случае беззнаковых, там где это надо/можно?

А потом другая нужда может возникнуть: "Сколько бы сделал Петя в августе, если бы прирост производительности был, как в январе, а в июле он сделал 5732 детали?"

И что? На каждый результат каждого действия писать другой тип?
Это же дополнительная работа программиста. Дополгнительное время.
А вот ради чего?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: Эх, товарищ, товарищ...
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 19:54
Оценка: :)
Здравствуйте, Erop, Вы писали:

АТ>>Есть такая полушутливая пословица "Если программа работает правильно, то это значит, что в ней содержится четное число ошибок". Вот этот пример кода выше — это как раз пример такой программы. Сначала был сделан ошибочный выбор в пользу знакового типа, а затем, чтобы "скомпенсировать" это ошибку, была добавлена еще одна — проверка значения [положительной по сути] знаковой переменной на отрицательность. В результате программа "работает".


АТ>>А я вот предпочитаю не делать первой ошибки вообще. Тогда и не надо будет вставлять в программу и "компенсаторы" этой ошибки. Ону просто будут не нужны. Удаление из кода соврешенно не нужных проверок, зачем-то туда засунутых — это не оптимизация, это банальное восттановление удобочитаемости и элегантности кода.


E>Я уже не знаю, как тебе ещё объяснить, что если из числа что-то вычитается, то оно естественным образом может стать отрицательным?

E>Ну правда может

Я уж не знаю, как тебе объяснить, что из того, что 3 — 5 = -2, совсем не следует того, что из корзины с тремя апельсинами можно вынуть пять апельсинов (и при этом там останется -2 апельсина).

E>Вот смотри, очередная итерация массива сверху вниз (считай, что размер массива знаковый):


E>
E>int step = 15;
E>for( int i = array.size() - 1; i >=0; i -= step )
E>    array[i] = i;
E>


E>Тут всё хорошо понятно. Хотя при выходе из цикла i становится отрицательным.


E>А что ты будешь делать в случае unsigned?


Не понимаю, что именно ты пытаешься доказать какими-то частными примерами, в то время как частные примеры никак не могут служить доказательством какого-то общего принципа. Чисто для иллюстрации, это пример можнно запросто преобразовать в беззнаковый "механическим" способом

unsigned step = 15;
for(unsigned i = array.size() - 1; i < array.size(); i -= step)
  array[i] = i;


Этот код коректен (при соблюдении введенных тобою же ограничений на размер массива). И ценнность такого "механического" преобразования в том, что при одинаковых ограничения на знаковый и беззнаковый код, такое преобразовние существует всегда. Поэтому мне вдвойне странно видеть здесь попытки "генерации" каких-то элементарных примеров.

Но мне лично результат такого механического преобразования он не нравится. Я могу, опять же механически, применить другой метод

unsigned step = 15;
for(unsigned i = array.size() + nstep - 1; i >= nstep; ) {
  i -= step;
  array[i] = i;
}


Это мне нравится больше.

А могу, под настроение, сделать даже так

if (array.size() > 0) {
  unsigned step = 15;
  for(unsigned i = array.size() - 1; ; i -= nstep) {
    array[i] = i;
    if (i < nstep)
      break;
  }
}
Best regards,
Андрей Тарасевич
Re[12]: вот и флейм пошёл уже... "А ты кто такой?" (с) :)
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 20:07
Оценка: :)
Здравствуйте, Erop, Вы писали:

Что касается флейма, то он, по-моему, "пошел" намного раньше и идет уже некоторое время — в первую очередь в заголовках Ваших сообщений.

АТ>>Хм... Ты, по-видимому, невнимательно читаешь. Не в первый раз уже. Я никогда не утверждал, что "atoi устарела больше, чем scanf" (чем scanf??? ). Я утверждал, что 'atoi' устарела больше, чем 'strtol', если уж пользоваться не совсем подходящим в данном случае словом "устарела"...


E>

E>Неверно. 'atoi' и иже с ними — функции "мертвые" и практической ценности не представляющие. Немножко "живее" — 'sscanf', который поддерживает unsigned, но и тот, к сожалению, неполноценен.


E>Выделение -- моё. (С) -- тут :shuffle:
Автор: Андрей Тарасевич
Дата: 14.11.06


Смысл, который я вкладывал в эту часть своего сообщения, заключается именно в том, что если 'sscanf' и "живее" 'atoi', то ненамного (см. выделенное Вами же слово "немножко"). Для устранения неоднозначностей я приписал дополнительно, что "и тот, к сожалению, неполноценен" (процитировано, но не выделено Вами). В непроцитированной же части моего сообщения сказано, что полноценными функциями преобразования являются функции групппы 'strto...'. По-моему, все это достаточно ясно из оригинального текста.

Попридираться к словам, разумеется, всегда можно, но вот нужно ли... С таки же успехом я могу попросить Вас показать мне, где в моем оригинальном сообщении Вы нашли слово "устарела".
Best regards,
Андрей Тарасевич
Re[9]: Эх, товарищ, товарищ...
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 20:53
Оценка: +1
Здравствуйте, Erop, Вы писали:

E>Ты просто забыл указать какой имеено из вариантов 1, 2 или 3 читабельнее, компактнее и переносимее оригинального, со знаковой арифметикой?


Читабельность... Во-первых — вещь субъективная. Во-вторых — это всегда trade-off — что-то теряем, что-то находим. Используя беззнаковый тип я средствами языка передал читателю (и компилятору) информацию о том, что даннная величина не имеет осмысленных отрицательных значений, тем самым повысив читаемость программы. А если какой-то цикл где-то и пострадал — ну так может оно того и стоило?

Компактность... Компактность не обладает самостоятельной ценностью. Разумная компактность есть лишь средство достижения читабельности. Рассмотрено выше. Или Вы о какой-то другой "компактности" говорите?

Преносимосить... Это уже что-то новенькое. Да вот и в соседнем сообщении она вдруг всплыла вместе с некоей "надежностью". На что именно Вы намекаете? Вам известны проблемы с переносимостью беззнаковых типов?

E>Ну или сойдёмся на том, что отрицательные числа придумали зануды математики, да и дело с концом.


Математики придумали много разных типов.

E>Ведь минус трёх апельсинов действительно в карман не положешь?


Да вот, я смотрю, кто-то все пытается и пытается их туда положить...
Best regards,
Андрей Тарасевич
Re[12]: Эх, товарищ, товарищ...
От: remark Россия http://www.1024cores.net/
Дата: 15.11.06 07:53
Оценка: +1
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Здравствуйте, remark, Вы писали:


R>>Проблема в том, что до компилятора С++ это очень плохо доходит (именно в плане знаковых/беззнаковых):


АТ>Ну так может надо взять другой компилятор?


Зачем брать другой компилятор взамен самого распространённого промышленного компилятора???
Нет, компиляторов с++, конечно много, но меня интересует именно промышленное использование.




АТ>Почему это вдруг этот вызов не должен компилироваться? Несколькими строчками выше ты говорил о предупреждениях. Опциональные предупреждения в таких ситуациях действительно стоило бы выдавать. Но "не скомпилируется"... Нет. О "не скомпилируется" не может быть и речи. Правила перобразования из int в unsigned четко определены языком и "модульное" поведение беззнаковых типов является одним из ценнейших свойств беззнаковых типов.


Почему, не может быть и речи.
Мне кажется естественным (для типизированных языков) поведение, что когда я пытаюсь передать параметр не того типа, что нужен, программа не компилируется.
В том то и дело, что правила преобразования определены. Ну а если бы там было определено, что после выполнения "int i = 1" в i заносится 2? Тоже всё нормально?


R>>Так же хотелось бы ожидать, что не скомпилируется и функция f3. По-моему это логично.

R>>Когда мы из одного числа вычитаем другое какой тип у нас получается? unsigned? Ну вообще-то по всем законам здравого смысла вроде как должен получится signed.

АТ>По видимому здравых смыслов больше, чем один. Беззнаковые типы, как это уже не раз говорилось раньше, реализуют модульную арифметику. В этой модульной арифметике нет отрицательных чисел. Вычитание одного безнакового числа из другого дает по прежнему беззнаковое число. Так это работает в модульной арифметике. Если кому-то подобная арифметика кажется неестесвенной или бесполезной в программистком форуме, то я в ответ могу лишь искренне удивиться.


Модульная арифметика, это не то, что обычно хотят люди:

unsigned update = 5;
unsigned stored = 5;
unsigned tolerance= 10;
bool const changed 
            = update > stored + tolerance
              ||
              update < stored - tolerance;




Вот ответь на простой вопрос: сколько будет 1 + 1? Ну или даже так поставим вопрос: какой процент людей на земле на этот вопрос не задумываясь ответит 2? Для какого процента людей это очевидно?
Я думаю, ты согласен, что это будет близко к 100%.
Так я думаю, что ты догадываешь к чему я веду Правильный ответ, который я загадал — 0. Естественно в модульной арифметике

В целом, необходимость беззнаковой арифметики, я, конечно, отрицатать не буду. И то, что ты говорил про ОС и менеджеры памяти, я тоже согласен. Но я не согласен с "Используя беззнаковый тип я средствами языка передал читателю (и компилятору) информацию о том, что даннная величина не имеет осмысленных отрицательных значений". Это так не работает.
Т.е. я бы сформулировал так: не надо использовать беззнаковую арифметику, не надо "передавать компилятору эту дополнительную информацию", надо всегда по-умолчанию использовать int, не надо никогда в прикладном коде использовать int, и тока если после использования int сильно припрёт и человек очень хорошо понимает, что делает, можно переходить к использованию unsigned.
Но никакого "а типа вроде как количество товара не может быть отрицательным... заведу-ка я для него unsigned... ой а что это у меня получилось 4 миллиарда товаров?".


R>>

АТ>

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[11]: Нужен ли unsigned
От: Шахтер Интернет  
Дата: 15.11.06 10:44
Оценка: :)
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Шахтер, Вы писали:


Ш>> // Нормализация хороша ещё и тем, что облегчает реализацию других операций с отрезком


К>А я говорил, что мне нужна длина как абсолютная величина?


А, понял. Я неверно воспринял условие.

К>И кстати. Что правильнее считать нормализацией — обмен координат или схлопывание в точку? (И кстати, в которую точку? первую или вторую).


Нормализация в данном примере -- вынуждение соблюдать инвариант класса (a<=b).
Как правильно -- зависит от смысла, который ты хочешь придать выражению Line(2,1).
Вполне возможно, что в этом случае лучше всего выбрасывть исключение.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[15]: Эх, товарищ, товарищ...
От: Erlond Россия  
Дата: 15.11.06 16:17
Оценка: :)
Здравствуйте, remark, Вы писали:

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


E>>Количество предметов — беззнаковая величина, она всегда положительна, а разница в количестве может быть как положительной,

E>>так и отрицательной. Так в чем проблема-то? Количество — unsigned int, а разница — int.

R>Хороший пример

R>Вот именно, что логично полагать, что разница — это int. Однако, если повнимательнее посмотреть, как работает с++, то можно удивиться. Разница между двумя количествами (unsigned) — это тоже unsigned! Не int!

R>

Ну почему же, всё зависит от задачи. Если разница между двумя unsigned не превышает INT_MAX, то следующий код вполне работоспособен.

unsigned int i = 3;
unsigned int j = 5;
int r = i-j;
std::cout << "r = " << r << std::endl;

Результат:
r = -2


Если же требуется получить только абсолютное значение разницы между двумя unsigned, то разница так же может быть unsigned.

P.S. Как быть с размером массива? Он тоже может быть отрицательным?
Re[17]: Эх, товарищ, товарищ...
От: Erlond Россия  
Дата: 15.11.06 17:51
Оценка: -1
Здравствуйте, vsb, Вы писали:

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


E>>Ну почему же, всё зависит от задачи. Если разница между двумя unsigned не превышает INT_MAX, то следующий код вполне работоспособен.


E>>
E>>unsigned int i = 3;
E>>unsigned int j = 5;
E>>int r = i-j;
E>>std::cout << "r = " << r << std::endl;
E>>

E>>Результат:
E>>
E>>r = -2
E>>


vsb>Строго говоря, здесь, по 4.7.3, implementation-defined behaviour.



4.7.3
If the destination type is signed, the value is unchanged if it can be represented in the destination type (and
bit-field width); otherwise, the value is implementation-defined.


Строго говоря — да, но если разница между двумя unsigned превышает INT_MAX, то должно работать, или я не прав?
Re[13]: А ради чего таки все эти усилия? :)
От: Erop Россия  
Дата: 16.11.06 12:00
Оценка: +1
Здравствуйте, Centaur, Вы писали:

C>Вот так арифметика устроена, что при сложении/вычитании двух произвольных k-битных чисел в результате получается (k+1)-битное. И независимо от знаковости приходится думать — то ли у нас значения таковы, что переполнения никогда не будет, то ли нам важна качественная картина, а младшим битом можно пожертвовать (и хранить (a+b)/2 вместо a+b), то ли вообще реализовать сложение/вычитание с насыщением.


Ну в подавляющем большинстве случаев, когда речь идёт о числах, надо просто брать достаточно большое целое, чтобы с запасом хватало.
Если от чего-то так нельзя, тггда начинается суровая оптимизация и всякие малочитабельные, трудноредактируемые и не особо переносимые подпрыгивания с бубнами.
Кто бы спорил.

Но всякие "обычные случаи" вроде итерации массива или подсчёта производительности Васи -- они-то тут при чём?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[18]: Эх, товарищ, товарищ...
От: Erop Россия  
Дата: 16.11.06 12:15
Оценка: -1
Здравствуйте, Erlond, Вы писали:

E>Строго говоря — да, но если разница между двумя unsigned превышает INT_MAX, то должно работать, или я не прав?

Нифига не так.
Предатавь себе, что знаковые числа хранятся в виде мантисы и знака, например
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[14]: А ради чего таки все эти усилия? :)
От: Centaur Россия  
Дата: 16.11.06 13:42
Оценка: +1
Здравствуйте, Erop, Вы писали:

E>Ну в подавляющем большинстве случаев, когда речь идёт о числах, надо просто брать достаточно большое целое, чтобы с запасом хватало.


E>Если от чего-то так нельзя, тггда начинается суровая оптимизация и всякие малочитабельные, трудноредактируемые и не особо переносимые подпрыгивания с бубнами.

E>Кто бы спорил.

Лично в моей практике «так нельзя» сплошь и рядом. Вот есть 8-битный беззнаковый битмэп размера 320 на 240, от него нужно посчитать производную d/dx. Если я продвину его до знакового 16-битного:

Вот ещё пример того, как не подумали над разрядностью. Это размеры файлов. Сплошь и рядом их держат в 32-битных переменных. Иногда даже знаковых. Очень весело смотреть, как прыгают индикаторы прогресса и средней скорости скачивания в FTP-клиенте при переходе через 2G, потом через 4G, и так далее.

Думать надо всегда, и никакие типы от этого не избавляют. Сегодня Вася делает 400 деталей в день, а завтра их сложат по всем рабочим завода за 30 лет, умножат на стоимость детали в японских йенах, и привет.
Re[15]: А ради чего таки все эти усилия? :)
От: Erop Россия  
Дата: 16.11.06 14:12
Оценка: +1
Здравствуйте, Centaur, Вы писали:

C>Думать надо всегда, и никакие типы от этого не избавляют. Сегодня Вася делает 400 деталей в день, а завтра их сложат по всем рабочим завода за 30 лет, умножат на стоимость детали в японских йенах, и привет.


Конечно думать надо всегда.
Просто когда речь идёт о знаковом целом, то думать надо как бы один раз. Сразу выяснить есть ли маза переполнить или нет.
Если таки есть -- прийдётся переходить на double или ещё чего дклать.

А в unsigned С++ числах надо думать о переполнении при кодировании кадой операции.
Ради чего это (кроме как радо того, чтобы не расслабляться) я так и не понял. Какая выгода от увеличения трудоёмкости кодирования?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[18]: Нет бы вот ответить ясно, а не пальцами кидаться :)
От: Erop Россия  
Дата: 16.11.06 14:22
Оценка: +1
Здравствуйте, saproj, Вы писали:

S>Детский сад! Вы уж простите меня. <climits> и <limits> позволяют писать программы, которые правильно заработают на платформах с разной разрядностью.



Вот смотри. Есть у тебя Вася. Рожает о детали в таких вот масштабах.
И всё-то у него хорошо. И пишешь ты про него программу. И у тебя всё хорошо. И ты даже файл limits умеешь использовать.
но беда в ся в том, что что же тебе делать, если ты выясняешь, что васины детали на этой конкретной платформе не помещаются в int?
Во всех плюсах понаписать всяких волшебных проверок? И если проверки провалились, то делать что?


E>>Так что если у вас есть реальная угроза переполнения, то всё и всегда очень плохо. Хоть знаковый он у вас, хоть беззнаковый

S>А еще память может не выделиться. Это тоже очень плохо?
Конечно. Обычно программы когда памяти не хватает просто отказываются работать и всё. В принципе последствия катастрофические

E>>Ну а теперь Внимаение! Вопрос!!!

E>>Почему я должен считать, что величины: "число деталей", "длина массива", "ширина окна", "сумма денег в кошельке" лучше выражаются модульной арифметикой по неизвестному модулю, а не знаковой, с неизвестно гден наступающим переполнением?

S>Довод что верхний предел выше, а програма понятнее вам не кажется убедительным?

1) Закладываться на то, что "верхний предел выше" в задае про Вася и детали крайне плохо. плохо потому, что то, что в signed величина не помещается, а в unsigned помещается -- это случайное стечение обстоятельств. Когда переполнение столь близко все вычисления надо вести очень аккуратно, всюду анализируя и проверяя возможность переполнения.

Намного позитивнее писать так, чтобы возможности переполнения вообще не было. Скажм Вася делает детали тысячами, а ты используешь 32-тный int. Тогда опасными становятся только квадраты количества деталлей. А всякие суммы-разности-ленейные комбинации нифига не опасны.

Зачем в такой ситуации связываться с unsigned?
Слово "зачем" подразумевает, что есть какая-то выгода.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[19]: Нет бы вот ответить ясно, а не пальцами кидаться :)
От: Аноним  
Дата: 16.11.06 14:29
Оценка: -1
E>Вот смотри. Есть у тебя Вася. Рожает о детали в таких вот масштабах.
E>И всё-то у него хорошо. И пишешь ты про него программу. И у тебя всё хорошо. И ты даже файл limits умеешь использовать.
E>но беда в ся в том, что что же тебе делать, если ты выясняешь, что васины детали на этой конкретной платформе не помещаются в int?
E>Во всех плюсах понаписать всяких волшебных проверок? И если проверки провалились, то делать что?

"Игривость" твоих сообщений и "простота" в общении уже несколько запарили. Если ты хорошо знаешь С/С++, то знаешь, что есть определенные гарантии для целочисленных типов. Переносимые программы на С/С++ вполне успешно пишутся, наверное потому, что люди их пишут а не тратят время на флейм о кошмарном ужасе беззнаковых.
Re[20]: Нет бы вот ответить ясно, а не пальцами кидаться :)
От: Erop Россия  
Дата: 16.11.06 15:55
Оценка: :)
Здравствуйте, saproj, Вы писали:

S>Ну вы, надеюсь, делаете проверку ошибок выделения памяти, чтобы программа хоть завершилась штатно, а не упала?

Ну ошибки нехватки памяи в вопросе итерации массива задом наперёд, ИМХО, немного левые

но если тебе интересно, то могу сказать, что проверок не делаем. Бросаем исключения.
при этом стабильно работаем не только на таких либеральных к нехватке памяти платформах, как Win32 и Linux, но и на таких сложных, как Mac OS Classic, скажем

S>На остальное отвечать не буду, т.к. ваш тон не нравится.

За тон прости. Но что-то тут меня чморят все, а на простые вопросы отвечают только три мысли
1) unsigned индексы хорошо, так как они такие же неудобные, как итераторы. поэтому не разбалуешься.
2) Есть лишний бит, и можно съэкономить на проверке x >= 0
3) Это даёт читателю кода информацию, что значение не может быть только неотрицательным.

Мне все три мысли кажутся странными
1) ИМХО это плохое свойство итераторв из STL, а не знаковых типов
2) Обе выгоды плохие. Если уж есть возможность переполнения, то надо писать иначе, чем просто при программировании простых целочисленных формул
3) Комментарий обычно и понятнее и полезнее и не портит код особенностями С++ опредеоления взаимодействия знаковых и беззнаковых целых
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Тараскевич vs Страуструп -- это круто :)
От: Erop Россия  
Дата: 16.11.06 16:49
Оценка: +1
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>В общем, "старейшин" надо уважать, но, скажем так, понимать, что все, что они говорят — это лишь монетка на ту или иную чашу весов. И, возможно, предназначавшаяся совсем не для ваших весов...


Итак. "Тараскевич vs Страуструп" -- куму поверим?
Страуструп пишет, что типа вот, опыт показывает, что нехорошо выходит с unsigned-то. В целом более или менее убедительно.
Типа бит завоёванный всё равно не спасает, а гарантий unsigmed никаких не даёт из-за парвил преобразования типов в С++.

И правда же вроде оба суждения классика

А что же говорит нам уважаемый Андрей?
Что unsigned индексы массивов таки понятнее?
Что unsigned таки гарантирует беззнаковость значения?
Что переполнения не избежать по любому, так что всё время надо писать код, который корректно работает в условиях переполнения и всюду на него закладываться?

или я что-то таки недопонял?
Я понимаю, что моя скромная персона не пользуеться уваженим, среди экспертов, но старик-то Срауструп может заслужил аргументированых возражений на свои соображения, а не довольно содержательных рассуждений на тему о том, что он и сам может уже передумал, да и может он это не для вас писал а для кого-то ещё и т. д.

В любом случае в мире, где живу я, идеии сильнее людей. Так что даже если Бьярн и передумал, аргументация-то его осталась
или это он всё писал для секретарш иногда применяющих С++ для своих нужд, а не для сверхкрутых перцев с КЫВТ/С++?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Нужен ли unsigned
От: Кодт Россия  
Дата: 16.11.06 17:08
Оценка: :)
Здравствуйте, Максим2006, Вы писали:

М>Было бы лучше иметь два разных типа — один для модульной арифметики, а второй — для беззнаковой (с UB при выходе за границы и иными правилами преобразования)


Модулярная арифметика может трактоваться как частный случай UB Так что unsigned замечательно справляется с обеими ролями.
Перекуём баги на фичи!
Re[5]: Справка
От: Erop Россия  
Дата: 16.11.06 17:43
Оценка: :)
Здравствуйте, Андрей Тарасевич,

"А ты кто такой?" -- это цитата из "Золотого телёнка"
Там перед тем как подраться герои выясняли друг у друга это сокраментальнео знание

Прости если процитировал неузноваемо
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[21]: Эх, товарищ, товарищ...
От: Erlond Россия  
Дата: 16.11.06 18:08
Оценка: :)
Здравствуйте, Erop, Вы писали:

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


E>>>Предатавь себе, что знаковые числа хранятся в виде мантисы и знака, например

E>>Не представляю. При чем тут это? Мы рассмотриваем сечас int и unsigned int.

E>А такие реализации таки бывают


Бывают, я же не говорил, что их не бывает. Я привёл конкретный пример с типами int и unsigned int. И задал по нему вполне конкретный вопрос.
Здесь идёт разговор о целых знаковых и целых беззнаковых числах, числа с плавающей запятой выходят за рамки этой дискуссии, т.к. они не являются целыми и т.к. они всегда знаковые
Re[4]: Нужен ли unsigned
От: Erlond Россия  
Дата: 16.11.06 18:24
Оценка: :)
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Кодт, Вы писали:


К>>Здравствуйте, Максим2006, Вы писали:


К>>Модулярная арифметика может трактоваться как частный случай UB Так что unsigned замечательно справляется с обеими ролями.


E>Да плохо она справляется.


E>Например, как всё-таки вычислить корректно разность двух unsigned чисел, ессли больше может быть любое?


Как вариант:
void main()
{
    unsigned int a, b, c;

    std::cin >> a >> b;

    c = (a > b) ? a - b : b - a;

    std::cout << c << std::endl;    
};
Re[4]: Нужен ли unsigned
От: Кодт Россия  
Дата: 17.11.06 09:21
Оценка: :)
К>>Модулярная арифметика может трактоваться как частный случай UB Так что unsigned замечательно справляется с обеими ролями.

E>Да плохо она справляется.

E>Например, как всё-таки вычислить корректно разность двух unsigned чисел, ессли больше может быть любое?

Ты не понял!
С арифметикой по модулю она справляется.
А с человеческой — честно реализует undefined behavior, как и просил Максим. Или ты хочешь, чтобы UB всегда форматировало диск?
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[5]: Мои извращённые желания
От: Erop Россия  
Дата: 17.11.06 12:59
Оценка: +1
Здравствуйте, Кодт, Вы писали:

E>>Например, как всё-таки вычислить корректно разность двух unsigned чисел, ессли больше может быть любое?


К>Ты не понял!

К>С арифметикой по модулю она справляется.
К>А с человеческой — честно реализует undefined behavior, как и просил Максим. Или ты хочешь, чтобы UB всегда форматировало диск?

Да знаю я с чем и как она справляется.

Вот у меня есть две положительные величины. Те жа самые пять апельсинов у тебя и три у меня.
Я хочу уметь вычислить разность. Ну типа "на сколько у меня больше"
При этом я вовсе не хочу получить 0xFFFFFFFE а хочу получить -2. Правда извращённое желание?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Нужен ли unsigned
От: Аноним  
Дата: 17.11.06 13:22
Оценка: +1
АТ>>>Также стоит упомянуть, что в С++ во многих контекстах выбор в пользу знаковых типов сдела на уровне языка и стандартной билиотеки. Сделан давно и навсегда. Это и 'size_t', и 'sid::vector<>:size_type' и т.п.
А>>Это не аргумент. Там тоже люди, и они могли не представлять к каким последствиям это может привести. Сдается мне что беззнаковые типы они выбрали по причине что неотрицательные числа "должны" представляться беззнаковыми числами (то что ты и говоришь) а не чтобы выгадать один бит. И тем не менее сам Бьярн использует int в циклах, к примеру, хотя если уж следовать стандарту, то он должен был бы писать unsigned.

E>Мне кажется, что в stl сделали выбор в пользу беззнаковых типов потому что итерация ими больше походит на итерацию указателями и итераторами.

Ну а размер контейнера? Размеры-то имеет смысл прибавлять или отнимать.
Re[6]: Мои извращённые желания
От: Erlond Россия  
Дата: 17.11.06 13:54
Оценка: +1
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Кодт, Вы писали:


E>>>Например, как всё-таки вычислить корректно разность двух unsigned чисел, ессли больше может быть любое?


К>>Ты не понял!

К>>С арифметикой по модулю она справляется.
К>>А с человеческой — честно реализует undefined behavior, как и просил Максим. Или ты хочешь, чтобы UB всегда форматировало диск?

E>Да знаю я с чем и как она справляется.


E>Вот у меня есть две положительные величины. Те жа самые пять апельсинов у тебя и три у меня.

E>Я хочу уметь вычислить разность. Ну типа "на сколько у меня больше"
E>При этом я вовсе не хочу получить 0xFFFFFFFE а хочу получить -2. Правда извращённое желание?

Это и есть -2 в доп. коде

    int a = 0xFFFFFFFE;
    std::cout << a;
Re[15]: Видимо ошибка в кончерватории :)
От: Erlond Россия  
Дата: 17.11.06 13:58
Оценка: :)
E>За лекбез спасибо, но
E>1) Нет никакой гарантии, что на всех машинах будет двоичный доп. код и будет 32-разрядный int.
E>2) Тот, кто программирует "просто числа", скажем производительность Васи или итерацию массива, при использовании беззнаковой арифметики всё время должен помнить обо всех этих особенностях реализации Кто-нибудь наконец ответит за ради чего?

По 1 пункту, я писал следующее:

Возьмём ваш пример с"-1" для 32-х разрядного регистра


Этот пример был для современных процессоров семейства х86 с 32-х быитным словом и представлением числа в доп. коде. К тому же разрядность регистра не так важна, в любом случае, при представлении числа "-1" в доп.двоичном коде получите все единицы. Главное здесь то, что представление знаковых чисел и беззнаковых отличается, и приведение знакового отрицательного числа к беззнаковому не даст ничего хорошоего.

По 2-му пункту: в общем-то тот, кто программирует, должен помнить, что в процессор оперирует с числами конечной точности представления, которая ограничена числом разрядов, отводимых по этот тип данных. И нужно знать особенности каждого типа данных, тем более в С++, т.к. он очень чувствителе к типам данных. Зачем открещиваться от какой-то части языка, если можно выучить это и использовать, там, где это требуется. Мне кажется не разумно использовать знаковый тип данных для тех величин, которые не должны стать отрицательными.
Re[17]: Видимо ошибка в кончерватории :)
От: Erlond Россия  
Дата: 17.11.06 14:50
Оценка: :)
Здравствуйте, Erop, Вы писали:

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



E>>Мне кажется не разумно использовать знаковый тип данных для тех величин, которые не должны стать отрицательными.


E>Ради чего?


А в чём, собственно, вопрос?
Re[8]: Мои извращённые желания
От: Андрей Тарасевич Беларусь  
Дата: 17.11.06 15:31
Оценка: -1
Здравствуйте, Erop, Вы писали:

E>Но вообще мне всё равно надо не "-2 в доп. коде для регистра такой-то разрядности", а просто -2 число такое.


Ну здрасьте? "Число" — математическая абстракция. Само "число" невозможно "получить". Его даже вообразить тольком нельзя. Все "числа", котрые мы можем получить, увидеть, потрогать или, скажем, понюхать — это на самом деле не "числа", а разнообразные представления чисел. Вариантов представлений много и дополнителный код — лишь один из них. И какой-то вариант в любом случае равно придется выбирать. А "просто -2 число такое" — так не бывает.
Best regards,
Андрей Тарасевич
Re[5]: мои измышления про unsigned, size_t и стандарт
От: Erop Россия  
Дата: 18.11.06 07:52
Оценка: -1
Здравствуйте, night beast, Вы писали:

NB>По поводу Страуструпа. Если бы все было так однозначно, то vector::size_type был бы интом.


Собственно я подумал и понял почему ни size_t, ни размер std::vector, ни его индекс не могут быть в С/С++ знаковым типом.
Это всё происходит из-за так называемой совместимости.

Действительно, никто не запрещает в C++ иметь очень большие объекты. Напимер объект размером почти со всю адресуемую память. Или vector.
Мало того, такие реализации наверняка были, когда компьютеры были слабее ZX Spectrum. Не пресоналки, а реальные такие компьютеры. Большие-пребольшие.

Так что если мы хотим сформулировать стандарт языка, который будет описывать и такие архитектуры, мы просто не можем выбрать другой тип, кроме unsigned

В некотором смысле это просто следствие того, как было принято делать компьютеры. Только и всего.


Теперь предлагаю посмотреть на это дело с другой стороны.
В конце концов переносимость C++ программ -- это миф.
Попробуйте написать сложную программу, которая легко переживёт перенос на платформу сильно другой разрядности. Скажем из 32-бит в 16?
Нифига у вас не выйдет. Всё равно переполнения будут вас преследовать и всякие другие проблемы.

С другйо стороны в прогамме объект "размером почти со всю память" может быть только один (если он вообще такой красивый нужен).
Так что его всё равно прийдётся при переносе докручивать ручками.

Я бы вот докручивал только если произойдёт переход на такую платформу. А заранее жизнь себе не усложнял бы
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[21]: Давай немного подробнее?
От: Erlond Россия  
Дата: 18.11.06 10:57
Оценка: :)
Ну кому-то это кажется удобным, кому-то нет.

По поводу typedef int int_for_unsigned_values это уже перебор. Обсуждается не само слово unsigned, а тип данных и модульная арифметика. Мне кажется, что данная "шутка юмора" здесь неуместна.

Опять же тут есть такая беда, что часто число плохо ограничено сверху. Ну скажем число апельсинов. Вот я там складывал что-то вычитал, как потом написать assert, чтор всё хорошо получилось?


Очень просто, если при сложении получилось число меньшее, чем каждое из слагаемых — переполнение, аналогично для вычитатния — если результат больше, чем числа, учавствовавшие в вычитании — переполнение.

Вот смотри, есть два куска кода:

E>

E>for( int i = count - 1; i >= 0; i-- )
E>    do_somthing( i );
E>

E>и
E>
E>unsigned int i = count;
E>while( i > 0 ) {
E>    i--;
E>    do_somthing( i );
E>}
E>

Вот смотрю и вижу, что ты пытаешься писать код для беззнаковых чисел, как будто они знаковые, конечно такое работать не будет.

unsigned int i = 0;

while( i < count )
 {
    ++i;
    do_somthing( i );
}

Кстатии, если не имеет значения будет ли выполнен постфиксный или префиксный инкремент (декремент), то лучше использовать префексный, т.к. не создаётся временного объекта, это связно с особенностью реализации этих операций.

По поводу статьи , я просто хотел сказать, что то, что работало на дебаге, может разчъехаться на релизе, тем более, если код с ошибкой, которая пока проезжает.
Re[9]: У синьора есть опыт?
От: Erop Россия  
Дата: 21.11.06 17:01
Оценка: +1
Здравствуйте, Erlond, Вы писали:

E>А что мешает ввести проверку? Вводишь условие, что в файле должно быть не больше UINT_MAX строк (или INT_MAX). Для 32-битной платформы это будет 2^32 -1, а для 16-ти битной 2^16-1.


Ну провалится твоя проверка. И что дальше?
Всё равно прийдётся переписывать

У меня, к сожалению, такой опыт есть. Я вот и утверждаю, что переносимость в том смысле, который предполагается в стандарте -- это миф.
Всё равно призходится подкручивать и отлажиавть

просто я так скромно подозреваю, что если у вас случится так, что самый большой объект в программе начнёт существенно использовать беззнаковость size_t, а исходная платформа будет WIN32 скажем, или Linux, то в программе будет много других проблем, кроме типа способа итерации ьайт этого мега-объекта.

так что с практической точки зрения совместимость такого рода ИМХО никакой ценности не имеет
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[11]: вопрос вкуса и целей
От: Erop Россия  
Дата: 22.11.06 17:54
Оценка: +1
Здравствуйте, johny5, Вы писали:


E>>Вообще языки высокого уровня

J>C/C++ относятся к языкам низкого уровня. Дальше — asm
Это очень сложный терминологический вопрос.

ИМХО во многих задачах С++ можно использовать как язык выского уровня, а можно как низкого.
Всё зависит от инструкции кодировщика/проэктировщика

Собственно моё ИМХО состоит в том, что использоание unsigned типов для индексации массива -- шаг в сторону низкого уровня, а signed -- в сторону высокого.
Ну а куда идти -- вопрос вкуса и целей
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[11]: Егоизвращённые желания
От: FSD  
Дата: 22.11.06 18:33
Оценка: :)
Здравствуйте, johny5, Вы писали:


E>>Вообще языки высокого уровня


J>C/C++ относятся к языкам низкого уровня. Дальше — asm

аппаратноориентированные, кажись
... << Сила ночи, сила дня — одинакова х..ня!>>
Cила ночи, сила дня — одинакова х..ня!
Re[9]: про переносимость С++ и прочее
От: johny5 Новая Зеландия
Дата: 23.11.06 00:17
Оценка: :)
E>Пусть у нас какой-то 16-битный компик. Скажем типа БК-0010, кажется так его звали. Только ROM мало, а RAM много. Скажем 4 против 60 килобайт. И мы можем завести объект размером в 40 кило скажем. Как его размер представлялся бы в signed int? Так что куда не денешься -- а приходится брать unsigned тип для size_t и для размера вектора.

Верно.

E>С другой стороны если ты попробуешь перенести какую-то прогу тех самых контор, с int32_t на такой компик, то ты много-много гемора огребёшь!

E>Так что никакого реального выигрыша от того, что size_t "переносим" в смысле стандарта C++ при реальном переносе получить не удаётся.

А тут не верно. int32_t он на то и 32 что на всех платформах 32х битный целочисленный и переносимость будет 100%.
Конечно если на 16 битной машине нет 32х битных чисел вообще, то реализовать такой тип — придётся потрудиться. Главная цель — портируемость.

Конечно, я согласен, что применять "чистые" типы себе дороже, благо все стандартные библиотеки предоставляют свой набор intxx, unsignedxx типов (можно даже без макросов, просто подключив config.h) так что этой проблемы как бы не существует.



E>Собственно моё ИМХО состоит в том, что использоание unsigned типов для индексации массива -- шаг в сторону низкого уровня, а signed -- в сторону высокого.


Моё ИМХО: выбор signed/unsigned типа — решение проектировщика — это, я понимаю, высокий (абстрактный) уровень. Тут не учитываются детали имплементации а только декларируется соглашение API о принимаемых/возвращаемых значениях. В данном случае вы предоставляете "барьер", человек, предоставляющий unsigned значение должен удостовериться что он предоставляет его правильно, соответственно API может быть спокойна за знаковость значения и наоборот.

А неумение программиста работать с unsigned типом и вообще пренебрежение низкоуровневыми деталями, которые предоставляет язык — это уже совсем другая проблема и лечиться она повышением квалификации програмиста, повышением уровня warning-ов + концепция warning -> error, административными методами. В крайнем случае, можно сменить язык на более высокоуровневый, например на ваш FORTRAN.
Re[12]: Беззнаковые иллюзии
От: Пётр Седов Россия  
Дата: 15.12.06 16:33
Оценка: +1
Здравствуйте, johny5, Вы писали:

J>Используя только тип int вы понижаете декларативное свойство интерфейсов. Кроме как в комментарии к коду у вас не будет возможности сказать, что значение всегда должно быть положительным. В вашем примере:


J>
J>int get_buratino_apples(Buratino& )
J>


J>неочевидно, что функция не может вернуть например -1 как сигнал ошибки, и пользователь будет вынужден явно позаботиться, написав проверку (assert или if). Если он не позаботиться сразу, то позднее, имплементор функции get_buratino_apples может догадаться, что не для всяких буратин функция может вернуть правильное значение и тогда пользователи этой функции "огребут по полной".


J>прототип функции


J>
J>unsigned get_buratino_apples(Buratino& )
J>


J>гарантирует положительность ответа,

Здесь тоже непонятно, возвращает ли функция специальное значение. Функция может вернуть std::string::npos (функция std::string::find) или TLS_OUT_OF_INDEXES (функция TlsAlloc).

J>и если все возвращаемые значения потенциально возможны (т.е. у вас нет способа через возвращаемое значение заявить об ошибке),

А как это узнать из прототипа функции? Всё равно придётся читать комментарии или документацию. В обоих случаях (int и unsigned) прототип функции ничего не говорит про специальное возвращаемое значение.

J>то проверка на валидность объекта класса Buratino будет уже стоять внутри функции get_buratino_apples.
Пётр Седов (ушёл с RSDN)
Re[13]: Беззнаковые иллюзии
От: johny5 Новая Зеландия
Дата: 16.12.06 03:22
Оценка: +1
Хорошо, но вы согласны, что unsigned даёт просто больше декларативной информации чем int (целое и положительное vs целое)?
Re[2]: Нужен ли unsigned
От: Аноним  
Дата: 12.11.06 14:39
Оценка:
Здравствуйте, Centaur, Вы писали:

C>Здравствуйте, Аноним, Вы писали:


А>>Я решил попробовать писать "правильный" код. Для ширины например — unsigned, т.е. она не бывает отрицательной. И тд.

А>>Но как меня всякие мелочи задолбали, извините. Чуть чуть перепутал, и всё, 4 миллиарда, вся логика валится.

C>Нужно обращать внимание на warning’и компилятора. И иметь компилятор, который их сыплет по всякому поводу.


gcc, -Wall -Wextra
варнингов нет. Да и откуда ему знать, что получится при m_width — m_pageWidth: 10 или 0 или -10
Re[3]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 12.11.06 19:53
Оценка:
Здравствуйте, A.Lokotkov, Вы писали:

АТ>>Не совсем понятно, причем здесь именно -1.

АТ>>Также непонятно, откуда взялись эти 4 миллиарда.
AL>
AL>unsigned someCounter = 99;
AL>while(--someCounter >= 0)
AL>{
AL>  //ooops! infinite loop here
AL>} 
AL>


И? Неправильно реализованный цикл работает, разумеется, неправильно. И что из этого?
Best regards,
Андрей Тарасевич
Re[4]: Нужен ли unsigned
От: Michael7 Россия  
Дата: 12.11.06 20:05
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

AL>>
AL>>unsigned someCounter = 99;
AL>>while(--someCounter >= 0)
AL>>{
AL>>  //ooops! infinite loop here
AL>>} 
AL>>


АТ>И? Неправильно реализованный цикл работает, разумеется, неправильно. И что из этого?


Очень хороший пример.

Применение unsigned излишне нагружает программисту мозг, заставляя его лишнего следить за кодом, в то время как казалось бы он мог рассчитывать отдохнуть на более строгом контроле типов.
Re[5]: Нужен ли unsigned
От: Шахтер Интернет  
Дата: 13.11.06 10:07
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Андрей Тарасевич, Вы писали:


К><>

АТ>>Я не знаком ни с какими "потенциальными проблемами" беззнаковых типов. В моем коде, например, практически все целочисленные типы — беззнаковые, за исключением случаев, когда действительно приходится работать со знаковой величиной.
К><>

К>Не столько проблема, сколько неудобство (иногда).

К>В знаковой арифметике одно и то же неравенство можно выразить несколькими способами: x<y, x-y<0, 0<y-x, а в

В знаковой арифметике эти выражения точно так же не эквивалетны. Кроме того, x<0 не эквивалетно -x>0.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: Всё очень просто....
От: Шахтер Интернет  
Дата: 13.11.06 10:15
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Аноним, Вы писали:


А>>Что вы думаете по этому поводу?


E>signed -- для чисел

E>unsigned -- для флажков.

По-моему, это та простота, которая хуже воровства.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: Всё очень просто....
От: night beast СССР  
Дата: 13.11.06 13:11
Оценка:
Здравствуйте, Erop, Вы писали:

E>>>signed -- для чисел

E>>>unsigned -- для флажков.
Ш>>По-моему, это та простота, которая хуже воровства.

E>Ну прости, я ответил на вопрос, что же я таки думаю.

E>ИМХО выгоды от использования беззанковых чисел всегда какие-то призрачные.
E>Конечно есть какие-то специальные очень случаи, когда хочется именно беззнакового и именно 32-ного числа.

у беззнаковых чисел есть одно хорошее свойство -- все арифметические операции делаются по модулю.
но постоянная борьба с варнингами при сравнении знаковых и беззнаковых просто удручает.
Re[2]: А может пусть лучше оптимизатор сокращает? :) (-)
От: Erop Россия  
Дата: 13.11.06 16:03
Оценка:
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Всё очень просто....
От: Erop Россия  
Дата: 13.11.06 16:07
Оценка:
Здравствуйте, night beast, Вы писали:

NB>у беззнаковых чисел есть одно хорошее свойство -- все арифметические операции делаются по модулю.

NB>но постоянная борьба с варнингами при сравнении знаковых и беззнаковых просто удручает.


Поясни что ты имеешь в виду под этим "хорошим" свойством.
и от чего оно таки хорошее?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: А может проще таки быть проще? :)
От: Андрей Тарасевич Беларусь  
Дата: 13.11.06 17:28
Оценка:
Здравствуйте, Erop, Вы писали:


E>А может писать как-то попроще. Скажем так:


E>
E>int a[N];
E>for( int i = N - 1; i >= 0; i-- ) {
E>    a[i] = 0;
E>}
E>


E>Компиляторы у нас сейчас хорошие, оптимизирующие. Код вроде как тоже понятный


Не надо фиксироваться на частностях. Мои примеры — лишь иллюстрация общего принципа. Приведенный мною ранее пример доступа с помощью указателя (или итератора) производит честный последовательный доступ к элементам контейнера. Ты же в своем примере эмулируешь последовательный доступ при помощи произвольного доступа. В общем случае это, разумеется, невозможно. И никакой оптимизирующий компиялтор тут тебе не поможет.
Best regards,
Андрей Тарасевич
Re[8]: Не! проще таки лучше!
От: Erop Россия  
Дата: 13.11.06 17:49
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Не надо фиксироваться на частностях. Мои примеры — лишь иллюстрация общего принципа. Приведенный мною ранее пример доступа с помощью указателя (или итератора) производит честный последовательный доступ к элементам контейнера. Ты же в своем примере эмулируешь последовательный доступ при помощи произвольного доступа. В общем случае это, разумеется, невозможно. И никакой оптимизирующий компиялтор тут тебе не поможет.


Ты сейчас, ИМХО, находишься в плену идеологических абстракций. На мой взгляд, опять же, вредных, так как они ведут к запутыванию кода.
Тебе надо написать пример похожего на цикл для массива, цикла для списка, который тоже успешно реализует полседовательный досутп?

Много довольно лет жили не тужили во многих языках, где вообще никакого unsigned типа не было и всё было и них хорошо.
Что такого страшного случилось после разработки STL, что коллекции стало трудно итерировать старыми добрыми простыми и надёжными способами?


Чтобы было понятнее о чём это я, вот тебе два примера последовательного доступа:

вот тебе список:
not_std::list<my_struct> lst;
for( my_struct* current = lst.last(); current != 0; current = current->prev() )
{
    // тут что-то делают с current
}


А вот и файл:
while( !is_EOF( src ) {
    char buffer[bufer_size];
    int read_count = fread( src, buffer, buffer_size );
    assert( read_count > 0 );
    // тут обрабатываем read_count байт данных из buffer
}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: Не! проще таки лучше!
От: Андрей Тарасевич Беларусь  
Дата: 13.11.06 18:11
Оценка:
Здравствуйте, Erop, Вы писали:

АТ>>Не надо фиксироваться на частностях. Мои примеры — лишь иллюстрация общего принципа. Приведенный мною ранее пример доступа с помощью указателя (или итератора) производит честный последовательный доступ к элементам контейнера. Ты же в своем примере эмулируешь последовательный доступ при помощи произвольного доступа. В общем случае это, разумеется, невозможно. И никакой оптимизирующий компиялтор тут тебе не поможет.


E>Ты сейчас, ИМХО, находишься в плену идеологических абстракций. На мой взгляд, опять же, вредных, так как они ведут к запутыванию кода.


Абстракции ведут к consistency (единообразию?) — основному (если не единственному) средству НЕзапутывания кода. Непонятно только, почему именно "идеологических"...

E>Тебе надо написать пример похожего на цикл для массива, цикла для списка, который тоже успешно реализует полседовательный досутп?


Не совсем понимаю, причем здесь пример для списка, если речь шла именно о массиве.

E>Много довольно лет жили не тужили во многих языках, где вообще никакого unsigned типа не было и всё было и них хорошо.


Ну так когда-то и языков никаких не было. И тоже, вроде, жили.

E>Что такого страшного случилось после разработки STL, что коллекции стало трудно итерировать старыми добрыми простыми и надёжными способами?


Во-первых, в STL — это необходимость реализации именно абстракций. Поэтому стали пользоваться новыми добрыми простыми и надёжными способами. И они, похоже, даже добрее, проще и недежней. Что делает осмысленным из использование и за пределами STL.

Во-вторых, к STL все это отностся на самом деле мало. Эти "абстакции" зарыты намного глубже.

(Причины приведения примеров не совсем понятны).
Best regards,
Андрей Тарасевич
Re[6]: Нужен ли unsigned
От: Centaur Россия  
Дата: 13.11.06 18:14
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Отдельно, кстати, стоит заметить, что, несмотря на то, что большая часть машинных арифметических операций на популярных арихитектурах не требуют различения знаковых и беззнаковых типов, такие требования языков С/С++, как округление у нулю при целочисленном делении, зачастую таки приводят к генерации менее эффективного кода для знаковых типов.


В C++ такого требования в общем случае нет. Оно есть для положительных делимого и делителя; в противном случае поведение implementation-defined (C++03 5.6/4). В C — да, округление к нулю (C99 6.5.5/6).
Re[4]: Где тут ошибка
От: Андрей Тарасевич Беларусь  
Дата: 13.11.06 19:26
Оценка:
Здравствуйте, Erop, Вы писали:

E>1) реально size таким большим не бывает, так как в память плохо помещается


Ни предел типа 'size_t', ни предел типа 'int' никак не связаны с "помещаемостью в память".
Best regards,
Андрей Тарасевич
Re[7]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 13.11.06 19:58
Оценка:
Здравствуйте, Centaur, Вы писали:

АТ>>Отдельно, кстати, стоит заметить, что, несмотря на то, что большая часть машинных арифметических операций на популярных арихитектурах не требуют различения знаковых и беззнаковых типов, такие требования языков С/С++, как округление у нулю при целочисленном делении, зачастую таки приводят к генерации менее эффективного кода для знаковых типов.


C>В C++ такого требования в общем случае нет. Оно есть для положительных делимого и делителя; в противном случае поведение implementation-defined (C++03 5.6/4). В C — да, округление к нулю (C99 6.5.5/6).


Да, это так (С++ тем не менее неформально рекомендует придерживаться округления к нулю), но опять же это означает что в общем случае этот эффект имеет место.
Best regards,
Андрей Тарасевич
Re[4]: Нужен ли unsigned
От: Michael7 Россия  
Дата: 13.11.06 21:22
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Результат знакового целочисленного переполнения — UB. Беззнаковые типы реализуют арифметику по модулю, т.е. у них не бывает "переполнения" или, другими словами, традиционное переполнение у них приводит к однозначно оговоренному эффекту без какого-либо UB.


Да? Я загляну в стандарт и ещё раз перечитаю.

АТ>Нет. Уверенность есть. На уровне языка.


Хм. Буду перечитывать. Если так, то зря я раскритиковал пример.
Re[5]: Статья с примером ошибки
От: Пётр Седов Россия  
Дата: 13.11.06 23:52
Оценка:
Здравствуйте, remark, Вы писали:
R>Или вот ещё статья недавно проскакивала.
Статья "Built-in Type Safety?", автор Thomas Guest. Обсуждали статью здесь
Автор: eao197
Дата: 12.10.06
.
Пётр Седов (ушёл с RSDN)
Re[6]: Всё очень просто....
От: night beast СССР  
Дата: 14.11.06 05:07
Оценка:
Здравствуйте, Erop, Вы писали:

NB>>у беззнаковых чисел есть одно хорошее свойство -- все арифметические операции делаются по модулю.

NB>>но постоянная борьба с варнингами при сравнении знаковых и беззнаковых просто удручает.

E>Поясни что ты имеешь в виду под этим "хорошим" свойством.


здесь
Автор: Шахтер
Дата: 13.11.06


E>и от чего оно таки хорошее?


отсутствием UB
например твой код для swap'a двух беззнаковых будет рабочим
Re[5]: Нужен ли unsigned
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 14.11.06 06:14
Оценка:
Добавлю ещё чуть-чуть: нет функций преобразования С-строк к unsigned типам. Есть atoi, atol, atoi64. И ни одного unsigned.
Re[7]: Нужен ли unsigned
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 14.11.06 07:21
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Здравствуйте, Nuzhny, Вы писали:


N>>Добавлю ещё чуть-чуть: нет функций преобразования С-строк к unsigned типам. Есть atoi, atol, atoi64. И ни одного unsigned.


АТ>Неверно. 'atoi' и иже с ними — функции "мертвые" и практической ценности не представляющие. Немножко "живее" — 'sscanf', который поддерживает unsigned, но и тот, к сожалению, неполноценен. Настоящие функции преобразования строк к целым из библиотеки С — 'strtol' и 'strtoul' (плюс 'll' версии в С99), из которых последняя как раз unsigned.


Совсем мёртвые? А я для С-строк ими пользуюсь...
Надо переходить на std::num_get<>::get().
Re[7]: Нужен ли unsigned
От: Erop Россия  
Дата: 14.11.06 09:48
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Неверно. 'atoi' и иже с ними — функции "мертвые" и практической ценности не представляющие.

А почему?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Решите тогда задачу
От: Roman Odaisky Украина  
Дата: 14.11.06 10:51
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>И все таки интересно, какую связь этой задачи с данной дискуссией видит автор?


А ты попробуй ее реши

Хинт:
-1 % 10 = -1
-1 % 10u = 5
(хотя хотелось бы видеть 9)

Как эту задачу решить правильно, я затрудняюсь сказать. В псевдокоде она решается одной строчкой:
unsigned f(unsigned n, int s)
{
    return s % n;
}
но правила C/C++ чуть изменяют поведение оператора % (по сравнению с математической его версией), в результате чего всё становится с ног на голову.
До последнего не верил в пирамиду Лебедева.
Re[6]: Нужен ли unsigned
От: remark Россия http://www.1024cores.net/
Дата: 14.11.06 11:08
Оценка:
Здравствуйте, Кодт, Вы писали:

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


К>Практически согласен со всем, кроме вот этого


R>>Обратных же примеров, когда замена unsigned на signed ломает код, нет!

R>>Если не считать, что у unsigned чуть больше диапазон. Но стоит ли оно того? Если уж надо хранить действительно большие числа, то имхо лучше воспользоваться int64_t. Тут и диапазон действительно больше, чем у int и проблем не будет.

К>Как только мы начинаем упражняться в работе с битами, проблемы сразу же появляются.

К>- приведение типов (всем хорошо известно, как переводить char в int: (int)(unsigned char)ch)
К>- сдвиг (SHR для беззнаковых и SAR для знаковых)
К>- битовые поля
К>
К>struct bitz
К>{
К>    unsigned u : 1; // принимает значения 0 и 1
К>    int      i : 1; // принимает значения... сюрприз! 0 и -1, потому что старший (единственный) бит - знаковый
К>};
К>



Согласен. Я немного погорячился с таким всеобъемлющим заявлением.
Тогда заявление надо ограничить до "обычных чисел" без битов, флагов и т.д.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Всё очень просто....
От: Шахтер Интернет  
Дата: 14.11.06 14:46
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Шахтер, Вы писали:


E>>>signed -- для чисел

E>>>unsigned -- для флажков.
Ш>>По-моему, это та простота, которая хуже воровства.

E>Ну прости, я ответил на вопрос, что же я таки думаю.

E>ИМХО выгоды от использования беззанковых чисел всегда какие-то призрачные.

Речь идет не а выгодах. Речь идет о том, зачем вообще нужна беззнаковая арифметика (см. заглавную тему).
Она нужна для решения огромного количества задач.

Например, напиши struct IPHeader без беззнаковых типов. Или сделай алгоритм вычисления CRC (а так же SHA, DES, длинная арифметика и.т.п.).

E>Конечно есть какие-то специальные очень случаи, когда хочется именно беззнакового и именно 32-ного числа.


E>Но, это очень большая редкость. Я вот припоминаю только один случай.


Не надо обобщать свой опыт на всю индустрию.

E>Обычно беззнаковые числа хочется использовать для каких-то объектов, которые числами не являютчся (скажем над ними не производят арифметических действий, например).

E>Это или какие-то ID или сборки флагов или ещё какие-нибудь хитрые конструкции. но никак не результат сложения/вычитания/деления/умножения/взятия остатка.

E>пример о котором я помню -- млпдшее слово в руками сделанном двухсловном числе.


E>Кроме того беззнаковость числа ничего хорошего ни в CT ни в RT не гарантирует.


Это утверждение мне непонятно. А что гарантирует знаковость числа?

E>Ну а выгоды я хотел бы узнать (кроме, конечно, выгоды в один бит)


E>Часто выгода в один бит всё равно бесполезна. Ну и потом обычно это всё непереносимо


Что именно непереносимо? И почему? Или слово непереносимо используется в другом значении?
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[8]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 14:59
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Андрей Тарасевич, Вы писали:


АТ>>Неверно. 'atoi' и иже с ними — функции "мертвые" и практической ценности не представляющие.

E>А почему?

Потому что не предоставляют никаких осмысленных средств для отлавливания "нечисловых" входных строк и, более существенно, порождают неопределенное поведение в случае переполнения.

'sscanf' позволяет отлавливать "кривые" входы, но опять же порождает неопределенное поведение при переполнении.
Best regards,
Андрей Тарасевич
Re[6]: Нужен ли unsigned
От: Шахтер Интернет  
Дата: 14.11.06 15:29
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Добавлю ещё чуть-чуть: нет функций преобразования С-строк к unsigned типам. Есть atoi, atol, atoi64. И ни одного unsigned.


Ты наверно хотел сказать -- нет в CRT. Ну и что?
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[8]: Нужен ли unsigned
От: Шахтер Интернет  
Дата: 14.11.06 15:31
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Андрей Тарасевич, Вы писали:


АТ>>Неверно. 'atoi' и иже с ними — функции "мертвые" и практической ценности не представляющие.

E>А почему?

Например, потому что не дают никакой диагностики.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[5]: Решите тогда задачу
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 15:48
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Здравствуйте, Андрей Тарасевич, Вы писали:


АТ>>И все таки интересно, какую связь этой задачи с данной дискуссией видит автор?


RO>А ты попробуй ее реши


Я ее уже давно решил. Мое решение выглядит так

unsigned f(unsigned n, int s)
{
  return s >= 0 ? s % n : n - (-s - 1) % n - 1;
}


RO>Хинт:

RO>
RO>-1 % 10 = -1
RO>-1 % 10u = 5
RO>
(хотя хотелось бы видеть 9)


Да, но непоcредственно для решения данной задачи и в первом случае хотелось бы видеть '9', а не '-1'. Проблема тут не в знаковости/беззнаковости, а в рекомендуемом в С/С++ (требуемом в С99) поведении операторов деления и взятия остатков, о которых ты сам же пишешь ниже. Знаковый тип тоже не дает желаемого результата. Поэтому я снова спрашиваю: какое это все имеет отношение к обсуждаемому вопросу?

(Да, о поведении выражений со смешанными знаковыми/беззнаковыми операндами надо помнить. Но в этом-то примере основная проблема именно в делении.)

RO>Как эту задачу решить правильно, я затрудняюсь сказать. В псевдокоде она решается одной строчкой:

RO>
RO>unsigned f(unsigned n, int s)
RO>{
RO>    return s % n;
RO>}
RO>
но правила C/C++ чуть изменяют поведение оператора % (по сравнению с математической его версией), в результате чего всё становится с ног на голову.


Совершенно верно, но переход к знаковым типам ничего в данном случае не решает.
Best regards,
Андрей Тарасевич
Re[5]: Решите тогда задачу
От: Шахтер Интернет  
Дата: 14.11.06 15:57
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Здравствуйте, Андрей Тарасевич, Вы писали:


АТ>>И все таки интересно, какую связь этой задачи с данной дискуссией видит автор?


RO>А ты попробуй ее реши


Можно мне?

unsigned mod(unsigned n,int s)
 {
  if( s>=0 ) return unsigned(s)%n;
  
  return n-1-(-unsigned(s)-1)%n;
 }


RO>Как эту задачу решить правильно, я затрудняюсь сказать. В псевдокоде она решается одной строчкой:

RO>
RO>unsigned f(unsigned n, int s)
RO>{
RO>    return s % n;
RO>}
RO>
но правила C/C++ чуть изменяют поведение оператора % (по сравнению с математической его версией), в результате чего всё становится с ног на голову.


C/C++ тут не причем. Причем здесь -- аппаратура. Поведение деления при отрицательных операндах может быть разным на разных машинах.
Это прблема не языка, а нестандартизованности знаковой арифметики.

Собственно говоря, ты привел хороший пример задачи, не решаемой без привлечения беззнаковых чисел.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[5]: А почему так "немножечко нервно"? :)
От: Erop Россия  
Дата: 14.11.06 16:41
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>А то что без беззнаковых типов невозможно писать надежный и переносимый код в этом и во многих других случаях.

Ну это просто враньё
Есть просто вагоны софта с знаковыми числавми и переносимого и вообще по всякому хорошего.

Кроме всего прочего, если мы таки всё ещё обсуждаем итерацию массива в обратном порядке, то я хотел бы узнать про источники ненадёжности или непеиеносимости такого вот кода:

int size = ***;
my_array<***> array( size );
for( int i = size - 1; i >= 0; i-- )
    array[i] = 0;




E>>1) реально size таким большим не бывает, так как в память плохо помещается
Ш>Неверно. На Win32 -- если система загружена с опцией 3GB. На Win64 вообще int 32 разрядный а size_t 64.

Ну-ну. Давай, попробуй, а потом расскажешь про двухгигабайтные массивы под 3Gb.


Ну а что касается, довольно таки пока что мифической истории про террабайтные массивы под Win64, то даже и там проблема будет не с тем, что индекс знаковый, а с тем, что индекс 32-разрядный

В дырку на стыке знаковости/беззнаковости на 64-битных индексах попасть ещё сложнее, чем на 32-разрядных


E>>2) Лично я и std::vector не пользуюсь. Пользуюсь массивами из другой библиотеки, там размер массива int
Ш>Да ради бога.
Нервный ты какой-то.
Нет бы вот чтобы спокойно обсудить что и как
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Всё очень просто....
От: Erop Россия  
Дата: 14.11.06 16:50
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Речь идет не а выгодах. Речь идет о том, зачем вообще нужна беззнаковая арифметика (см. заглавную тему).

Ш>Она нужна для решения огромного количества задач.

1) Вообще беззнаковая арифметика нужна в C++ в основном для того, чтобы работать со всякими странными объектами, которые на самом деле числами не являются, но от чего-то в C и С++ числами предстваленны. Вот в паскале нету никакой беззнаковой арифметики и ничего.
Да и в математике тоже нету

Это исключительно С-шное изобретение. Для того, чтобы иногда хитрые всякие трюки можно было сделать не на асме, а на типа языке высокого уровня.

Ш>Например, напиши struct IPHeader без беззнаковых типов. Или сделай алгоритм вычисления CRC (а так же SHA, DES, длинная арифметика и.т.п.).


Вот конкретно длинная арифметика -- единственный пример, который я посмню, где именно беззнаковая арифметика была в тему.
А CRC нет никакой проблемы считать и так и сяк и по всяк.

E>>Конечно есть какие-то специальные очень случаи, когда хочется именно беззнакового и именно 32-ного числа.

E>>Но, это очень большая редкость. Я вот припоминаю только один случай.
Ш>Не надо обобщать свой опыт на всю индустрию.
Ну ты тоже вроде только его и привёл

E>>Обычно беззнаковые числа хочется использовать для каких-то объектов, которые числами не являютчся (скажем над ними не производят арифметических действий, например).

E>>Это или какие-то ID или сборки флагов или ещё какие-нибудь хитрые конструкции. но никак не результат сложения/вычитания/деления/умножения/взятия остатка.

E>>Кроме того беззнаковость числа ничего хорошего ни в CT ни в RT не гарантирует.

Ш>Это утверждение мне непонятно. А что гарантирует знаковость числа?
Тоже ничего не гарантирует, кроме того, что труднее попасть в переполнение по вычитанию
Но в целом в математике и вообще в мозгу нормального среднего человека числа вполне себе знаковые. И в предметной области тоже занковые.
Даже если какая-то конкретная числовая величина беззнаковая, то разность двух таких величин всё равно будет знаковой.
Короче знаковая арифметика -- общий случай высокого уровня. Беззнаковая -- хитрый полухаккерский трюк, который удобно устроить на почти всех компьютерах. Но для того, чтобы такой трюк использовать, надо бы чтобы он был чем-то лучше простого и понятного общего случая


E>>Ну а выгоды я хотел бы узнать (кроме, конечно, выгоды в один бит)

E>>Часто выгода в один бит всё равно бесполезна. Ну и потом обычно это всё непереносимо
Ш>Что именно непереносимо? И почему? Или слово непереносимо используется в другом значении?

Ну та ситуация, что 31 бита не хватает, а 32 хватает.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Всё очень просто....
От: MaximE Великобритания  
Дата: 14.11.06 18:22
Оценка:
Шахтер wrote:

> Речь идет не а выгодах. Речь идет о том, зачем вообще нужна беззнаковая

> арифметика (см. заглавную тему).
> Она нужна для решения огромного количества задач.
>
> Например, напиши struct IPHeader без беззнаковых типов. Или сделай
> алгоритм вычисления CRC (а так же SHA, DES, длинная арифметика и.т.п.).

Забавно, что без unsigned невозможно хранить в однобитовом члене 1. С signed
только -1 и 0.

#include <iostream>

int main()
{
     struct { int i : 1; } a = { 0 }, b = { 1 };
     std::cout << a.i << '\n' << b.i << '\n';
}


[max@k-pax test]$ bin/test
0
-1


--
Maxim Yegorushkin

No Microsoft product was used in any way to write or send this text.
If you use a Microsoft product to read it, you're doing so at your own risk
Posted via RSDN NNTP Server 2.0
Re[9]: Нужен ли unsigned
От: Erop Россия  
Дата: 14.11.06 18:34
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>>>Неверно. 'atoi' и иже с ними — функции "мертвые" и практической ценности не представляющие.

E>>А почему?

АТ>Интересно видеть, как пользователь Erop помечает сообщение через "выразить несогласие" и при этом одновременно задает вопрос "Почему?". На каком же основании Вы, уважаемый Erop, выражаете свое несогласие, не понимая при этом, о чем идет речь?



Я не согласен, что atoi устарела больше, чем scanf, уважаемый эксперт Андрей
Мало того, твои аргументы меня так и не убедили

Хотя в целом я согласен, что можно бы пользоваться и более высокоуровневым инструментом, чем atoi.

Тем не менее, часто довольно бывает так, что лексический анализ текстового потока происходит в одном месте, а преобразование чисел представленных строками в числовое представление в другом
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Эх, товарищ, товарищ...
От: Erop Россия  
Дата: 14.11.06 18:42
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Есть такая полушутливая пословица "Если программа работает правильно, то это значит, что в ней содержится четное число ошибок". Вот этот пример кода выше — это как раз пример такой программы. Сначала был сделан ошибочный выбор в пользу знакового типа, а затем, чтобы "скомпенсировать" это ошибку, была добавлена еще одна — проверка значения [положительной по сути] знаковой переменной на отрицательность. В результате программа "работает".


АТ>А я вот предпочитаю не делать первой ошибки вообще. Тогда и не надо будет вставлять в программу и "компенсаторы" этой ошибки. Ону просто будут не нужны. Удаление из кода соврешенно не нужных проверок, зачем-то туда засунутых — это не оптимизация, это банальное восттановление удобочитаемости и элегантности кода.


Я уже не знаю, как тебе ещё объяснить, что если из числа что-то вычитается, то оно естественным образом может стать отрицательным?
Ну правда может

Вот смотри, очередная итерация массива сверху вниз (считай, что размер массива знаковый):

int step = 15;
for( int i = array.size() - 1; i >=0; i -= step )
    array[i] = i;


Тут всё хорошо понятно. Хотя при выходе из цикла i становится отрицательным.

А что ты будешь делать в случае unsigned?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Нужен ли unsigned
От: Erop Россия  
Дата: 14.11.06 18:44
Оценка:
Здравствуйте, Lepsik, Вы писали:

L>Без второго большая часть известных библиотек практически нереализуема. Конкретный пример — нет ни одной ОС написанной на языках без безнаковых типов


Ну вопросы-то вызывает не использования беззнаковых целых в С++ для представления всяких странных объектов (наборов флажков, представления содержимого памяти, битовых масок, пикселей на экране и т. п.)

А в использовании беззнаковой арифметики, как более надёжной, наглядной и переносимой, например в задаче итерации массива от элементов с большим индексом к элементам с маленьким
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Ну много хаков есть в плюсах....
От: Erop Россия  
Дата: 14.11.06 19:38
Оценка:
Здравствуйте, MaximE, Вы писали:


ME>Забавно, что без unsigned невозможно хранить в однобитовом члене 1. С signed

ME>только -1 и 0.

Ну это же всё хаки, обусловленные таким вот "удачным" определеним языка С++.

Ясно, что елси вы как-то хитро-прехитро пакуете данные и экономите каждый бит, то там нужны всяческие извраты и bit fields и unsigned и много чего ещё.

Но когда ты занимаешься просто какими-то вычислениями.
Скажем итерериуешь массив, возможно с какими-то пропусками, скажем.
Ну на кой вот с unsigned страдать гемором?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[11]: вот и флейм пошёл уже... "А ты кто такой?" (с) :)
От: Erop Россия  
Дата: 14.11.06 19:42
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:


АТ>Хм... Ты, по-видимому, невнимательно читаешь. Не в первый раз уже. Я никогда не утверждал, что "atoi устарела больше, чем scanf" (чем scanf??? ). Я утверждал, что 'atoi' устарела больше, чем 'strtol', если уж пользоваться не совсем подходящим в данном случае словом "устарела"...



Неверно. 'atoi' и иже с ними — функции "мертвые" и практической ценности не представляющие. Немножко "живее" — 'sscanf', который поддерживает unsigned, но и тот, к сожалению, неполноценен.


Выделение -- моё. (С) -- тут :shuffle:
Автор: Андрей Тарасевич
Дата: 14.11.06

За то, что я опечатался в столь важном повтором ss приношу свои извинения. Это я не с целью кого-то запутать.
Это я с клавой дружу плохо
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: Эх, товарищ, товарищ...
От: Erop Россия  
Дата: 14.11.06 20:00
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

E>>Вот смотри, очередная итерация массива сверху вниз (считай, что размер массива знаковый):


E>>
E>>int step = 15;
E>>for( int i = array.size() - 1; i >=0; i -= step )
E>>    array[i] = i;
E>>




1)
АТ>
АТ>unsigned step = 15;
АТ>for(unsigned i = array.size() - 1; i < array.size(); i -= step)
АТ>  array[i] = i;
АТ>


2)
АТ>
АТ>unsigned step = 15;
АТ>for(unsigned i = array.size() + nstep - 1; i >= nstep; ) {
АТ>  i -= step;
АТ>  array[i] = i;
АТ>}
АТ>


3)
АТ>
АТ>if (array.size() > 0) {
АТ>  unsigned step = 15;
АТ>  for(unsigned i = array.size() - 1; ; i -= nstep) {
АТ>    array[i] = i;
АТ>    if (i < nstep)
АТ>      break;
АТ>  }
АТ>}
АТ>



Всё так.
Ты просто забыл указать какой имеено из вариантов 1, 2 или 3 читабельнее, компактнее и переносимее оригинального, со знаковой арифметикой?

Ну а что касется прмера с корзинами и апельсинами, то тебе сюда
Автор: k55
Дата: 22.11.05

Ну или сойдёмся на том, что отрицательные числа придумали зануды математики, да и дело с концом.
Ведь минус трёх апельсинов действительно в карман не положешь?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 20:16
Оценка:
Здравствуйте, Erop, Вы писали:

E>А в использовании беззнаковой арифметики, как более надёжной, наглядной и переносимой, например в задаче итерации массива от элементов с большим индексом к элементам с маленьким


А нельзя ли пояснить, откуда вдруг взялись "надежность" и "переносимость" в этой компании? Что, есть какие-то проблемы с переносимостью беззнаковых типов? С надежностью? Интересно было бы послушать.
Best regards,
Андрей Тарасевич
Re[8]: Нужен ли unsigned
От: Андрей Тарасевич Беларусь  
Дата: 14.11.06 20:23
Оценка:
Здравствуйте, MaximE, Вы писали:

>> Неверно. 'atoi' и иже с ними — функции "мертвые" и практической ценности

>> не представляющие. Немножко "живее" — 'sscanf', который поддерживает
>> unsigned, но и тот, к сожалению, неполноценен. Настоящие функции
>> преобразования строк к целым из библиотеки С — 'strtol' и 'strtoul'
>> (плюс 'll' версии в С99), из которых последняя как раз unsigned.

ME>Чем sscanf неполноценен?


Тем, что, согласно его спецификации, переполнение при переводе вызывает неопределеное поведение.

ME>По крайней мере в gnu libc, sscanf использует strtoul(l). Было бы удивительно,

ME>если бы другие реализации так же не поступали — обыкновенный code reuse.

Это разумно, но это деталь реализации.
Best regards,
Андрей Тарасевич
Re[11]: Эх, товарищ, товарищ...
От: Андрей Тарасевич Беларусь  
Дата: 15.11.06 06:05
Оценка:
Здравствуйте, remark, Вы писали:

R>Проблема в том, что до компилятора С++ это очень плохо доходит (именно в плане знаковых/беззнаковых):


Ну так может надо взять другой компилятор?

R>
R> ...
R>unsigned f2(unsigned)
R>{
R>    int i = -1;
R>    return i;
R>}

R>unsigned f3(unsigned i, unsigned i2)
R>{
R>    return i - i2;
R>}

R>int main()
R>{
R>    int i = -1;
R>    f1(i);
R>    f2(i);
R>    f3(1, 2);
R>}
R>


R>msvc71 /w4 — ни одного варнинга!


R>Например, когда я пытаюсь передать std::string как парметр int, совершенно логично программа не скомпилируется.

R>Фактически программист хочет ожидать, что в приведённом примере не скомпилируется вызов f2. А почему нет? Разьве это не разные типы?

Почему это вдруг этот вызов не должен компилироваться? Несколькими строчками выше ты говорил о предупреждениях. Опциональные предупреждения в таких ситуациях действительно стоило бы выдавать. Но "не скомпилируется"... Нет. О "не скомпилируется" не может быть и речи. Правила перобразования из int в unsigned четко определены языком и "модульное" поведение беззнаковых типов является одним из ценнейших свойств беззнаковых типов.

R>Так же хотелось бы ожидать, что не скомпилируется и функция f3. По-моему это логично.

R>Когда мы из одного числа вычитаем другое какой тип у нас получается? unsigned? Ну вообще-то по всем законам здравого смысла вроде как должен получится signed.

По видимому здравых смыслов больше, чем один. Беззнаковые типы, как это уже не раз говорилось раньше, реализуют модульную арифметику. В этой модульной арифметике нет отрицательных чисел. Вычитание одного безнакового числа из другого дает по прежнему беззнаковое число. Так это работает в модульной арифметике. Если кому-то подобная арифметика кажется неестесвенной или бесполезной в программистком форуме, то я в ответ могу лишь искренне удивиться.

(Другому оппоненту: а модульную арифметику, кстати, тоже придумали математики...)

R>

Best regards,
Андрей Тарасевич
Re[10]: Нужен ли unsigned
От: Кодт Россия  
Дата: 15.11.06 09:43
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш> // Нормализация хороша ещё и тем, что облегчает реализацию других операций с отрезком


А я говорил, что мне нужна длина как абсолютная величина?
Если бы это было так, то с самого начала формула b-a < d-c логически неправильна вне зависимости от типов. Тогда о чём спор, когда в программе смысловой косяк?..

Здесь другой физический смысл.
Может быть, я меряю скорость, которая может быть отрицательной величиной даже на участке пути с положительными координатами. Ну или какие-то аналогичные ситуации: приращение уровня сигнала, например.

И кстати. Что правильнее считать нормализацией — обмен координат или схлопывание в точку? (И кстати, в которую точку? первую или вторую).
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[13]: Эх, товарищ, товарищ...
От: Erlond Россия  
Дата: 15.11.06 14:28
Оценка:
Я тоже позволю себе вмешаться в дискуссию, котора уже достойна быть помещённой в раздел "Священные войны"

Интересные аргументы приводятся "противниками" типа unsigned int, в основном всё сводится к тому, что
"ну не надо знаковую величену представлять безннаковой". И правильно, не надо. Никто этого не предлагает.

Количество предметов — беззнаковая величина, она всегда положительна, а разница в количестве может быть как положительной,
так и отрицательной. Так в чем проблема-то? Количество — unsigned int, а разница — int.

И ещё меня, допустим, удивляет реализация CArray, где метод GetSize() возвращает int, размер
массива может быть отрицательным??

Зачем брать другой компилятор взамен самого распространённого промышленного компилятора???
Нет, компиляторов с++, конечно много, но меня интересует именно промышленное использование.


Проверял в VS 2005 /W4 тоже ни одного предупреждения, но это скорее минус компилятора, а не беззнаковых типов.

Модульная арифметика, это не то, что обычно хотят люди:

unsigned update = 5;
unsigned stored = 5;
unsigned tolerance= 10;
bool const changed 
            = update > stored + tolerance
              ||
              update < stored - tolerance;


Если люди — пользователи, то обычно они хотят, чтобы программа решала поставленную задачу и имела "человеческий" интерфейс. А программист должен знать типы данных языка, С++ не прощает легкомысленного программирования. (Предчувствую ответ — "давайте уволим всех ламеров")

Вот ответь на простой вопрос: сколько будет 1 + 1? Ну или даже так поставим вопрос: какой процент людей на земле на этот вопрос не задумываясь ответит 2? Для какого процента людей это очевидно?
Я думаю, ты согласен, что это будет близко к 100%.
Так я думаю, что ты догадываешь к чему я веду Правильный ответ, который я загадал — 0. Естественно в модульной арифметике


Правильный ответ — не обязательно 0, смотря по какому модулю, можно ведь взять 3, 5, 28... Если брать по модулю 2 — то 0, и это нормально, странно, если бы было по другому.

В целом, необходимость беззнаковой арифметики, я, конечно, отрицатать не буду. И то, что ты говорил про ОС и менеджеры памяти, я тоже согласен. Но я не согласен с "Используя беззнаковый тип я средствами языка передал читателю (и компилятору) информацию о том, что даннная величина не имеет осмысленных отрицательных значений". Это так не работает.
Т.е. я бы сформулировал так: не надо использовать беззнаковую арифметику, не надо "передавать компилятору эту дополнительную информацию", надо всегда по-умолчанию использовать int, не надо никогда в прикладном коде использовать int, и тока если после использования int сильно припрёт и человек очень хорошо понимает, что делает, можно переходить к использованию unsigned.
Но никакого "а типа вроде как количество товара не может быть отрицательным... заведу-ка я для него unsigned... ой а что это у меня получилось 4 миллиарда товаров?".


А что, лучше когда у нас получается -5 единиц товара? Почему странно получить 4 млрд, а -5 — нормально?

P.S. Андрею Тарасевичу — большой респект
Re[14]: Спрашиваю исключительно из интереса
От: Erop Россия  
Дата: 15.11.06 15:04
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Спрашиваю исключительно из интереса: что есть реально рабочее, умеющее красиво перебирать элементы коллекций, позволяющее писать абстрактные алгоритмы, легковесное? Вот ты какими неитераторами пользуешься?


Я пользуюсь библиотекой, которую ты скорее всего не знаешь. Она чем-то похожа на MFC в области коллекций. Sort там реализован, а остальное вроде как бывает нужно крайне редко.
Собственно обычно мне не нужно писать абстрактные алгоритмы.
Вернее не совсем так. Нет нужды писать настолько простые абстрактные алгоритмы, чтобы итераторы там могли как-то существенно помочь
Во всяком случае основные трудозатраты идут не на это.

Общий смысл такой, что что-то вроде двухпутевого слияния я пишу просто на C++, что-то вроде следующей перестановки мне вообще ни разу не пригодилось, и по милости Божей, мне пока удаётся так проектировтаь свои разработки, что нет нужды переходить от массива к списку или ещё куда-то, когда уже написано два вагона кода.

При этом мы таки пишем довольно сложные, и даже довольно переносимые программы, с очень сложными алгоритмами, данными, навороченными оболочками и т. п.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[12]: А ради чего таки все эти усилия? :)
От: Centaur Россия  
Дата: 15.11.06 17:28
Оценка:
Здравствуйте, Erop, Вы писали:

E>Вот вроде как естественная нужда, сравнить у кого в апреле был прирост производительности больше и Васи или у Пети.

E>Вот какая будет реализация в случае последовательно знаковых типов и какая в случае беззнаковых, там где это надо/можно?

Вот так арифметика устроена, что при сложении/вычитании двух произвольных k-битных чисел в результате получается (k+1)-битное. И независимо от знаковости приходится думать — то ли у нас значения таковы, что переполнения никогда не будет, то ли нам важна качественная картина, а младшим битом можно пожертвовать (и хранить (a+b)/2 вместо a+b), то ли вообще реализовать сложение/вычитание с насыщением.
Re[11]: Где тут ошибка
От: Максим2006 Беларусь  
Дата: 16.11.06 07:50
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

[]

АТ>Может ли быть дельта между значениями отрицательной — это вопрос постановки задачи. Согласно сделанной тобой постановке, эта величина может быть отрицательной. Прекрасно — это означает, что даннная величина будет представлена знаковым значением.


АТ>Вот и все.


Тут нужно уточнить каким знаковым. Если имеется в виду знаковое, по числу битов равное беззнаковому (int и unsigned int), то, наверное, не всё так просто (как хотелось бы). Ведь разность двух беззнаковых может дать как отрицательное значение, так и положительное. При этом в обоих этих случаях возможно непопадание в диапазон signed int. Как же тут быть? Может быть всегда использовать знаковое с более широким диапазоном? Наверное, всё зависит от конкретных допустимых значений в выражениях...

АТ>Я подозреваю, что следующим шагом будет попытка убедить меня в том, что "очень легко ошибиться" при вычитании первого из второго, т.е. забыть перевести вычисления в рамки знаковых типов. Над подобными аргументами можно только посмеяться.

Согласен
Re[12]: Видимо ошибка в кончерватории :)
От: Erop Россия  
Дата: 16.11.06 12:07
Оценка:
Здравствуйте, Максим2006, Вы писали:

М>Тут нужно уточнить каким знаковым. Если имеется в виду знаковое, по числу битов равное беззнаковому (int и unsigned int), то, наверное, не всё так просто (как хотелось бы). Ведь разность двух беззнаковых может дать как отрицательное значение, так и положительное. При этом в обоих этих случаях возможно непопадание в диапазон signed int. Как же тут быть? Может быть всегда использовать знаковое с более широким диапазоном? Наверное, всё зависит от конкретных допустимых значений в выражениях...


Тем не менее в простых задачах. Вроде учёта производительност Васи, итерации массива, который находится в памяти, работы с размерами окон и т. п. всегда можно выбрать такой целый знаковый тип, что если вы не будете как-то особенно усиленно хаметь, то никакого переполнения не встретите. И будет вам счастье.

Ну а если вы пишете код, который расчитывает на специфицированное поведение при переполнении unsigned, и считаете его понятным и переносимым (от чего-так -- я совершенно не понимаю Вот скажем такая простая штука, как unsigned(-1) % 10 уже равна неизвестно чему), то конечно я не могу засавить вас посмотреть на мир, где можно писать целочисленные вычисления вообще без переполнений, но зачем вы остальных уверяете что это невозхможно я не понимаю
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[16]: Нет бы вот ответить ясно, а не пальцами кидаться :)
От: Erop Россия  
Дата: 16.11.06 12:57
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Во-первых, приведение типа в данном случае — это не какой-то "странный каприз" спецификации языка, это преход между двумя приниципиально различными по своей природе арифметиками — обычной и модульной. Такой преход — событие настолько существенное, что делать его неявно в любом случае не стоит и, по этой причине, выполнение явного приведения типа более чем оправдано. Таких моментов в С/С++ навалом и избежать их не удастся отказом от безнаковых типов.



Собсвтенно язык C++ в области целых чисел довольно убогий. Увы и ах.
Есть всего два варианта целых типов.

Один реализует знаковую арифметику, в которой нельзя оперировать слишком большими (обычно не всегда известно насколько большими) числами, и второй -- модульная арифметика по не всегда известному нам заранее модулю.

Почему я пишу ""по неизвестному заранее", "неизвестно заранее насколько большие" и т. п.?
Да потому что разрядность сишных целых никто не гарантирует

Так что если у вас есть реальная угроза переполнения, то всё и всегда очень плохо. Хоть знаковый он у вас, хоть беззнаковый

Ну а теперь Внимаение! Вопрос!!!

Почему я должен считать, что величины: "число деталей", "длина массива", "ширина окна", "сумма денег в кошельке" лучше выражаются модульной арифметикой по неизвестному модулю, а не знаковой, с неизвестно гден наступающим переполнением?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[17]: Нет бы вот ответить ясно, а не пальцами кидаться :)
От: saproj  
Дата: 16.11.06 13:42
Оценка:
Здравствуйте, Erop, Вы писали:

E>Собсвтенно язык C++ в области целых чисел довольно убогий. Увы и ах.

E>Есть всего два варианта целых типов.

E>Один реализует знаковую арифметику, в которой нельзя оперировать слишком большими (обычно не всегда известно насколько большими) числами, и второй -- модульная арифметика по не всегда известному нам заранее модулю.


E>Почему я пишу ""по неизвестному заранее", "неизвестно заранее насколько большие" и т. п.?

E>Да потому что разрядность сишных целых никто не гарантирует

Детский сад! Вы уж простите меня. <climits> и <limits> позволяют писать программы, которые правильно заработают на платформах с разной разрядностью.

E>Так что если у вас есть реальная угроза переполнения, то всё и всегда очень плохо. Хоть знаковый он у вас, хоть беззнаковый


А еще память может не выделиться. Это тоже очень плохо?

E>Ну а теперь Внимаение! Вопрос!!!


E>Почему я должен считать, что величины: "число деталей", "длина массива", "ширина окна", "сумма денег в кошельке" лучше выражаются модульной арифметикой по неизвестному модулю, а не знаковой, с неизвестно гден наступающим переполнением?


Довод что верхний предел выше, а програма понятнее вам не кажется убедительным?
Re[14]: Закон перехода количества в качество.
От: Erop Россия  
Дата: 16.11.06 14:01
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Это еще что! Когда они думали об обычной арифметике, они также не ограничивали себя диапазоном -0x80000000..0x7FFFFFFF. И даже диапазоном 0x8000000000000000..0x7FFFFFFFFFFFFFFF не ограничивали! Я слышал историю про то, как в древности один мужик за изобретение какой-то игры (поддавки, кажется) затребовал 2^64-1 пшеничных зерна. И это было тогда, до инфляции...


Что-то мне подсказывает, что он таки столкнулся с переполнением, при попытке взыскать долг
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Нужен ли unsigned
От: Максим2006 Беларусь  
Дата: 16.11.06 14:04
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Я решил попробовать писать "правильный" код. Для ширины например — unsigned, т.е. она не бывает отрицательной. И тд.

А>Но как меня всякие мелочи задолбали, извините. Чуть чуть перепутал, и всё, 4 миллиарда, вся логика валится.
А>Если int-ы хоть можно проверить на -1, то unsigned-ы как проверишь? Непонятно.
А>Собственно вопрос, оправдан ли такой геморрой? Или сделать :%s/unsigned/int/g и жить счастливой жизнью?
А>С одной стороны вроде бы unsigned идеологически лучше. Но с другой, не получается у меня нормально с ними писать. Каждый раз, когда фунцию с аргументом типа unsigned вызываешь, надо проверять, не передастся ли туда отрицательное число, а если бы она была int, то проверку можно было бы сделать внутри функции (ну не писать же
А>
А>void f(unsigned x)
А>{
А>    if ((int)x < 0) // something bad
А>}
А>
)

А>Что вы думаете по этому поводу?

Предлагаю послушать старейшин... (Б.Стр-п, 2005)

4.4 ...
...
Типы unsigned идеально подходят для задач, в которых память интерпретируется как массив битов. Использование unsigned вместо int с целью заработать лишний бит для представления положительных целых почти всегда оказывается неудачным решением. Использование же объявления unsigned для гарантии того, что целое будет неотрицательным, почти никогда не сработает из-за правил неявного преобразования типов.
...


Лично я до сих пор руководствовался тем принципом, что если объект, который представляет переменная, неотрицателен по смыслу, то лучше использовать unsigned. Это отражает смысл, помогает читать и понимать код. Это можно сравнить по красоте с модификатором const...

В то же время, я рассчитываю на поведение unsigned как отдельного типа, со схожим с int поведением. Но это не так. Например, выход за границу диапазона не является UB.

Было бы лучше иметь два разных типа — один для модульной арифметики, а второй — для беззнаковой (с UB при выходе за границы и иными правилами преобразования)
Re[13]: Видимо ошибка в кончерватории :)
От: Максим2006 Беларусь  
Дата: 16.11.06 14:30
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Максим2006, Вы писали:


М>>Тут нужно уточнить каким знаковым. Если имеется в виду знаковое, по числу битов равное беззнаковому (int и unsigned int), то, наверное, не всё так просто (как хотелось бы). Ведь разность двух беззнаковых может дать как отрицательное значение, так и положительное. При этом в обоих этих случаях возможно непопадание в диапазон signed int. Как же тут быть? Может быть всегда использовать знаковое с более широким диапазоном? Наверное, всё зависит от конкретных допустимых значений в выражениях...


E>Тем не менее в простых задачах. Вроде учёта производительност Васи, итерации массива, который находится в памяти, работы с размерами окон и т. п. всегда можно выбрать такой целый знаковый тип, что если вы не будете как-то особенно усиленно хаметь, то никакого переполнения не встретите. И будет вам счастье.

Что касается итерации по массиву, у меня и так счастье потому что с этой задачей практически не сталкиваюсь. За меня это делает стд-алгоритм. А коль уж приходится, то применяю нелюбимую Вами технику скользящего указателя. Какой смысл тратить время на вычисление индекса? да я покурить успею, если сложить все эти задержки на большом массиве!
В остальном согласен. К сожалению. Потому что идея unsigned мне очень нравится, но, к сожалению, язык её не поддерживает как хотелось бы.

E>Ну а если вы пишете код, который расчитывает на специфицированное поведение при переполнении unsigned, и считаете его понятным и переносимым (от чего-так -- я совершенно не понимаю Вот скажем такая простая штука, как unsigned(-1) % 10 уже равна неизвестно чему), то конечно я не могу засавить вас посмотреть на мир, где можно писать целочисленные вычисления вообще без переполнений, но зачем вы остальных уверяете что это невозхможно я не понимаю

Код, основанный на переполнении unsigned, лучше поместить в класс/нэймспейс с соответствующим названием, потому что интуитивно не понятно что имеется в виду под именем типа unsigned.
Вы может меня с кем-то спутали?.. Я никого не уверял, что невозможно "писать целочисленные вычисления вообще без переполнений"
Re[19]: Нет бы вот ответить ясно, а не пальцами кидаться :)
От: saproj  
Дата: 16.11.06 14:43
Оценка:
Здравствуйте, Erop, Вы писали:

E>>>Так что если у вас есть реальная угроза переполнения, то всё и всегда очень плохо. Хоть знаковый он у вас, хоть беззнаковый

S>>А еще память может не выделиться. Это тоже очень плохо?
E>Конечно. Обычно программы когда памяти не хватает просто отказываются работать и всё. В принципе последствия катастрофические
Ну вы, надеюсь, делаете проверку ошибок выделения памяти, чтобы программа хоть завершилась штатно, а не упала?

На остальное отвечать не буду, т.к. ваш тон не нравится.
Re[2]: В целом о целых :)
От: Erop Россия  
Дата: 16.11.06 15:02
Оценка:
Здравствуйте, Максим2006, Вы писали:

М>Было бы лучше иметь два разных типа — один для модульной арифметики, а второй — для беззнаковой (с UB при выходе за границы и иными правилами преобразования)


У меня, если честно, другие предпочтнеия.
Я бы предпочёл, чтобы в C++ был какой-то такой тип int, который вёл бы себя понятно и переносимо. В том числе и при делении отрицательных чисел и при переполнеии и т. п.

Ну и было бы два низкоуровневых урода, для трюков с битами и оптимизацией. Одни -- беззнаковое число, поддерживаемое аппаратурой, а другой -- знаковое поддерживаемое аппаратурой

Вот в C почти так, а в С++ от чего-то упорствуют

Собственно какой есть круг проблем вообще?

1) аппаратура слишком разнообразнео поддерживает отрицательные числа
2) аппаратура слишком по разному ведёт себя при делении отрицательных чисел
3) аппаратура поддерживает такую "беззанковую" арефметику, какую поддерживает. ("Беззанковая" в кавычках, потому, что она реально вообще арифметика по модулю какой-то степени двойки)
4) аппаратура слишком по-разному ведёт себя при сдвигах отрицательных чисел
5) аппаратура слишком по разному ведёт себя при попытках интерпретировать слишком большие беззнаковые числа как знаковые.

Вроде бы всё?

Теперь смотрим что бы мы хотели
1) Доступ к удобному и переносимому целому числу. Чему-то вроде float или double. Хотелось бы предсказуемого и переносимого поведения
2) Доступ к возможностям аппаратуры, для целей трюков с битами и оптимизации.
3) Возможность оптимизации всего этого дела транслятором.
4) Возможность писать простые всякие целочисленные выражения, в которых нет опасности переполнения без всякого размышления о поведении системы в случае переполнения (как мы это делаем с double), ну или, как компромис, с простыми пердусловиями какими-нибудь

Если к делу подходить так, то из имеющихся в современном С++ возможностей выбор не велик
1) Для операция с просто числами использовать int, или свой "безопасный тип", но обычно это не нужно, так как это паранойа.
2) Для трюклв с битами использовать unsigned, как более специфицированный.
3) В любом случае избегать деления и сдвигов отрицательных чисел, даже если тип signеd
Ну нету в C++ удобных средств для этих операций. Ну приходится жить с тем, что имеем. К счастью эти операции очень редко нужны.
4) Если хочется сказать, что метод CArray::Size() возвращает неотрицательные числа, то можно написать комментарий. Так же можно поступить. если он возвращает, напимер, целые числа и т. д.
ИМХО и понятнее и непредсказуемых последситвий намного меньше

С уважением.


Возможно суть спора состоит в том, что участники по разному понимают слово unsigned.
АФАИК в С++ это слово обозначает "арифметика по модулю какой-то определённой степени двойки"
Вроде как приверженцы unsigned размеров массивов не спорят с такой семантикой unsigned типов в С++.
Но от чего-то думают наглядным обозначать этим своеобразным ключевым словом величины, которые не могут быть отрицательными по семантике
ИМХО это так же логично, как обозначать, например, словом auto переменные, которые имеют отношение к автомобилям
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[20]: Нет бы вот ответить ясно, а не пальцами кидаться :)
От: Erop Россия  
Дата: 16.11.06 15:24
Оценка:
Здравствуйте, Аноним, Вы писали:

А>"Игривость" твоих сообщений и "простота" в общении уже несколько запарили. Если ты хорошо знаешь С/С++, то знаешь, что есть определенные гарантии для целочисленных типов. Переносимые программы на С/С++ вполне успешно пишутся, наверное потому, что люди их пишут а не тратят время на флейм о кошмарном ужасе беззнаковых.


Про "кошмарный ужас беззнаковых" я не соглашусь
Но вот о меня напримр тут пытаются убедить, что unsigned типы удобнее, лучше и надёжнее знаковых. Например в задаче итерации массива. Приводят самые разные аргументы. Почти все мне не понятны

С скажу так:
Для работы с числами unsigned типы неудобны.
Есть три ситуации. Третья редкая

1) Мне надо работать с целыми числами. При этом диапазон этих чисел таков, что можно найти такой целый тип, что опасность переполнения незначительна. Тогжа конечно нужно использовать знаковый целый.

2) Мне надо работать с битами или каким-то побитовыми штуками. Скажем с младшими разрядами длинного числа или со словом флагов. Тогда нужно использовать unsigned типы.

3) Не то не другое. Обычно это 1, но числа слишком большие. Хотя и не так. Тогда всё плохо. Разработка удорожается, код становится трудно поддерживаемым, дорогим и непонятным. Лучше бы научиться такой ситуации избегать. Например пререйти к double или ещё что-то придумать

Вот вся критика этой очень прагматичной схемы носит, КМК, совершенно идеологический, а не прагматический характер.

Ещё подробнее смотри здесь
Автор: Erop
Дата: 16.11.06
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Уточнение опечаток
От: Erop Россия  
Дата: 16.11.06 15:59
Оценка:
E>Если к делу подходить так, то из имеющихся в современном С++ возможностей выбор не велик
E>1) Для операция с просто числами использовать int, или свой "безопасный тип". Правда обычно и без специаольного "безопасного целого"удаётся обойтись, так как и с int уже терпимо, хотя конечно и геморно.
E>2) Для трюклв с битами использовать unsigned, как более специфицированный.
E>3) В любом случае избегать деления и сдвигов отрицательных чисел, даже если тип signеd
E>Ну нету в C++ удобных средств для этих операций. Ну приходится жить с тем, что имеем. К счастью эти операции очень редко нужны.
E>4) Если хочется сказать, что метод CArray::Size() возвращает неотрицательные числа, то можно написать комментарий. Так же можно поступить. если он возвращает, напимер, чётные числа и т. д.
E>ИМХО и понятнее и непредсказуемых последситвий намного меньше
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[21]: Нет бы вот ответить ясно, а не пальцами кидаться :)
От: saproj  
Дата: 16.11.06 16:32
Оценка:
Здравствуйте, Erop, Вы писали:

S>>Ну вы, надеюсь, делаете проверку ошибок выделения памяти, чтобы программа хоть завершилась штатно, а не упала?

E>Ну ошибки нехватки памяи в вопросе итерации массива задом наперёд, ИМХО, немного левые
Выбрось итерацию массива из головы . Я не писал ни о каких массивах.

E>но если тебе интересно, то могу сказать, что проверок не делаем. Бросаем исключения.

Хорошо, пусть бросаете исключения. Я под проверкой понимал любую обработку нехватки памяти.
Предлагаю также бросать ваше любимое исключение, если труженик Вася сделал столько деталей, что их количество больше чем numeric_limits<используемый беззнаковый тип>::max(). Это нужно делать не везде, а только в тех местах кода, где математически не доказана невозможность переполнения.

E>3) Комментарий обычно и понятнее и полезнее и не портит код особенностями С++ опредеоления взаимодействия знаковых и беззнаковых целых

А как же программистская мудрость что, если код нуждается в комментарии, значит его нужно переписать/изменить, чтобы он стал понятнее?
Использование знакового типа для количества произведенных Васей деталей — это по-моему уменьшение понятности кода.
Re[12]: Интересно, а как можно так сделать?
От: Erop Россия  
Дата: 16.11.06 16:34
Оценка:
spine! А как можно не согласиться с нижеследующим вопросом?

E>А вот ради чего?


Я не то, чтобы против, просто интеренсно понять логику собеседника
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[22]: Нет бы вот ответить ясно, а не пальцами кидаться :)
От: Erop Россия  
Дата: 16.11.06 16:40
Оценка:
Здравствуйте, saproj, Вы писали:

E>>но если тебе интересно, то могу сказать, что проверок не делаем. Бросаем исключения.

S>Хорошо, пусть бросаете исключения. Я под проверкой понимал любую обработку нехватки памяти.
S>Предлагаю также бросать ваше любимое исключение, если труженик Вася сделал столько деталей, что их количество больше чем numeric_limits<используемый беззнаковый тип>::max(). Это нужно делать не везде, а только в тех местах кода, где математически не доказана невозможность переполнения.

А толку-то?
Вот, если продолжать аналогию с памятью и её нехватками, то если на платформе её хватает, то всё хорошо, если не хватет, то я беру руки в ноги и налаживаю и оптимизирую, пока не хватит. А что делать с Васей, кторый наваял деталей столько что в unsigned int не лезет?
Тоже настраивать и оптимизировать и переписывать?

Ну дык тогда limits ничем нам не помог! Что так переписывать, что сяк переписывать

E>>3) Комментарий обычно и понятнее и полезнее и не портит код особенностями С++ опредеоления взаимодействия знаковых и беззнаковых целых

S>А как же программистская мудрость что, если код нуждается в комментарии, значит его нужно переписать/изменить, чтобы он стал понятнее?
S>Использование знакового типа для количества произведенных Васей деталей — это по-моему уменьшение понятности кода.

Ну тогда ты наверное легко объяснишь мне, почему "арифметика по модулю 0х1000000" выражает свойства числа деталей лучше чем "знаковая арифметика, не позволяющая работать с числами сильно превышающими миллиард"?
ОТветит мне кто-то на этот "простой" вопрос или нет?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[23]: Нет бы вот ответить ясно, а не пальцами кидаться :)
От: saproj  
Дата: 16.11.06 17:14
Оценка:
Здравствуйте, Erop, Вы писали:

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


E>>>но если тебе интересно, то могу сказать, что проверок не делаем. Бросаем исключения.

S>>Хорошо, пусть бросаете исключения. Я под проверкой понимал любую обработку нехватки памяти.
S>>Предлагаю также бросать ваше любимое исключение, если труженик Вася сделал столько деталей, что их количество больше чем numeric_limits<используемый беззнаковый тип>::max(). Это нужно делать не везде, а только в тех местах кода, где математически не доказана невозможность переполнения.

E>А толку-то?

E>Вот, если продолжать аналогию с памятью и её нехватками, то если на платформе её хватает, то всё хорошо, если не хватет, то я беру руки в ноги и налаживаю и оптимизирую, пока не хватит. А что делать с Васей, кторый наваял деталей столько что в unsigned int не лезет?
Ответ очень простой: перейти на uint64_t. Не надо препятствовать трудовым подвигам.

E>>>3) Комментарий обычно и понятнее и полезнее и не портит код особенностями С++ опредеоления взаимодействия знаковых и беззнаковых целых

S>>А как же программистская мудрость что, если код нуждается в комментарии, значит его нужно переписать/изменить, чтобы он стал понятнее?
S>>Использование знакового типа для количества произведенных Васей деталей — это по-моему уменьшение понятности кода.

E>Ну тогда ты наверное легко объяснишь мне, почему "арифметика по модулю 0х1000000" выражает свойства числа деталей лучше чем "знаковая арифметика, не позволяющая работать с числами сильно превышающими миллиард"?

E>ОТветит мне кто-то на этот "простой" вопрос или нет?

В случае с количеством деталей арифметика по модулю нам вряд ли нужна, мы просто не будем допускать превышения. (Разве что для более удобной проверки из примера 2 отсюда
Автор: Шахтер
Дата: 13.11.06
, но это мелочь.)
Re[4]: Тараскевич vs Страуструп -- это круто :)
От: night beast СССР  
Дата: 16.11.06 17:26
Оценка:
Здравствуйте, Erop, Вы писали:

АТ>>В общем, "старейшин" надо уважать, но, скажем так, понимать, что все, что они говорят — это лишь монетка на ту или иную чашу весов. И, возможно, предназначавшаяся совсем не для ваших весов...


E>Итак. "Тараскевич vs Страуструп" -- куму поверим?

E>Страуструп пишет, что типа вот, опыт показывает, что нехорошо выходит с unsigned-то. В целом более или менее убедительно.

Не хотелось влезать в вашу милую беседу, однако давайте будем уважать оппонентов.
Один раз возможно опечатка, но два уже тенденция Не стоит.

По поводу Страуструпа. Если бы все было так однозначно, то vector::size_type был бы интом.
Re[24]: Нет бы вот ответить ясно, а не пальцами кидаться :)
От: Erop Россия  
Дата: 16.11.06 17:27
Оценка:
Здравствуйте, saproj, Вы писали:

E>>Ну тогда ты наверное легко объяснишь мне, почему "арифметика по модулю 0х1000000" выражает свойства числа деталей лучше чем "знаковая арифметика, не позволяющая работать с числами сильно превышающими миллиард"?

E>>ОТветит мне кто-то на этот "простой" вопрос или нет?

S>В случае с количеством деталей арифметика по модулю нам вряд ли нужна, мы просто не будем допускать превышения. (Разве что для более удобной проверки из примера 2 отсюда
Автор: Шахтер
Дата: 13.11.06
, но это мелочь.)


Ну дык и знаковую мы тем более не переполним
Так всё-таки ответ на вопрос "почему лучше" будет каким? )
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[19]: Эх, товарищ, товарищ...
От: Erlond Россия  
Дата: 16.11.06 17:27
Оценка:
Здравствуйте, Erop, Вы писали:

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


E>>Строго говоря — да, но если разница между двумя unsigned превышает INT_MAX, то должно работать, или я не прав?

E>Нифига не так.
E>Предатавь себе, что знаковые числа хранятся в виде мантисы и знака, например
Не представляю. При чем тут это? Мы рассмотриваем сечас int и unsigned int.
Re[3]: Нужен ли unsigned
От: Erop Россия  
Дата: 16.11.06 17:28
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Максим2006, Вы писали:


К>Модулярная арифметика может трактоваться как частный случай UB Так что unsigned замечательно справляется с обеими ролями.


Да плохо она справляется.

Например, как всё-таки вычислить корректно разность двух unsigned чисел, ессли больше может быть любое?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[20]: Эх, товарищ, товарищ...
От: Erop Россия  
Дата: 16.11.06 17:40
Оценка:
Здравствуйте, Erlond, Вы писали:

E>>Предатавь себе, что знаковые числа хранятся в виде мантисы и знака, например

E>Не представляю. При чем тут это? Мы рассмотриваем сечас int и unsigned int.

А такие реализации таки бывают
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[25]: Нет бы вот ответить ясно, а не пальцами кидаться :)
От: saproj  
Дата: 16.11.06 17:47
Оценка:
Здравствуйте, Erop, Вы писали:

E>>>Ну тогда ты наверное легко объяснишь мне, почему "арифметика по модулю 0х1000000" выражает свойства числа деталей лучше чем "знаковая арифметика, не позволяющая работать с числами сильно превышающими миллиард"?

E>>>ОТветит мне кто-то на этот "простой" вопрос или нет?

S>>В случае с количеством деталей арифметика по модулю нам вряд ли нужна, мы просто не будем допускать превышения. (Разве что для более удобной проверки из примера 2 отсюда
Автор: Шахтер
Дата: 13.11.06
, но это мелочь.)


E>Ну дык и знаковую мы тем более не переполним


Во-первых непонятно почему "тем более".
Во-вторых никто не говорит что со знаковым типом нельзя написать безошибочный код для решения этой же задачи.

E>Так всё-таки ответ на вопрос "почему лучше" будет каким? )


Все уже сказано. Мною в последней строке этого
Автор: saproj
Дата: 16.11.06
сообщения. Другими людьми тоже сказано не раз. Обрати внимание как терпеливо и подробно объясняет Андрей Тарасевич. Не лишне будет еще раз сосредоточенно прочитать.
Re[14]: Видимо ошибка в кончерватории :)
От: Michael7 Россия  
Дата: 16.11.06 20:53
Оценка:
Здравствуйте, Erlond, Вы писали:

E>Очень просто, в компльютере числа представляются в дополнительном коде. Дополнительный код положительного числа равен самому числу, а чтобы получить дополнительный код отрицательно числа, нужно празрядно проинвертировать число, а затем, к тому что получилось прибавить 1.


Нет гарантии, что на всех системах целые отрицательные числа представляются с помощью дополнительного кода. Есть и другие способы представить целое отрицательное число. Как я понимаю, именно по причине различных способов представления, переполнение знаковой переменной в стандарте отнесено к UB.
Re[15]: Видимо ошибка в кончерватории :)
От: Erlond Россия  
Дата: 16.11.06 21:08
Оценка:
Здравствуйте, Michael7, Вы писали:

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


E>>Очень просто, в компльютере числа представляются в дополнительном коде. Дополнительный код положительного числа равен самому числу, а чтобы получить дополнительный код отрицательно числа, нужно празрядно проинвертировать число, а затем, к тому что получилось прибавить 1.


M>Нет гарантии, что на всех системах целые отрицательные числа представляются с помощью дополнительного кода. Есть и другие способы представить целое отрицательное число. Как я понимаю, именно по причине различных способов представления, переполнение знаковой переменной в стандарте отнесено к UB.


Согласен, я выразлся недостаточно точно, есть и другие способы представления отрицательных чисел, но насколько я помню в процессорах х86 используется дополнительный код.

В предыдущем посте я попытался объяснить, почему при приведении отрицателного числа к беззнаковому получается такой результат. Хотя интересна сама попытка такого приведения, чего этим хотели добиться?
Re[16]: Видимо ошибка в кончерватории :)
От: Erop Россия  
Дата: 17.11.06 12:39
Оценка:
Здравствуйте, Erlond, Вы писали:

E>В предыдущем посте я попытался объяснить, почему при приведении отрицателного числа к беззнаковому получается такой результат. Хотя интересна сама попытка такого приведения, чего этим хотели добиться?


Ну хорошо, такая вот попытка: (1u — 2u) % 10 месье устроит?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[14]: Видимо ошибка в кончерватории :)
От: Erop Россия  
Дата: 17.11.06 12:42
Оценка:
Здравствуйте, Erlond, Вы писали:

E>Таким образом дополнительный код числа "-1" — 0xFFFFFFFF, при приведении типов, в переменную типа unsigned int запишется именно 0xFFFFFFFF, в десятичной системе счисления это составляет 4 294 967 295. Явно видно, что остаток деления на 10 будет 5.


За лекбез спасибо, но
1) Нет никакой гарантии, что на всех машинах будет двоичный доп. код и будет 32-разрядный int.
2) Тот, кто программирует "просто числа", скажем производительность Васи или итерацию массива, при использовании беззнаковой арифметики всё время должен помнить обо всех этих особенностях реализации Кто-нибудь наконец ответит за ради чего?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Нужен ли unsigned
От: Erop Россия  
Дата: 17.11.06 12:47
Оценка:
Здравствуйте, Аноним, Вы писали:

АТ>>Также стоит упомянуть, что в С++ во многих контекстах выбор в пользу знаковых типов сдела на уровне языка и стандартной билиотеки. Сделан давно и навсегда. Это и 'size_t', и 'sid::vector<>:size_type' и т.п.

А>Это не аргумент. Там тоже люди, и они могли не представлять к каким последствиям это может привести. Сдается мне что беззнаковые типы они выбрали по причине что неотрицательные числа "должны" представляться беззнаковыми числами (то что ты и говоришь) а не чтобы выгадать один бит. И тем не менее сам Бьярн использует int в циклах, к примеру, хотя если уж следовать стандарту, то он должен был бы писать unsigned.


Мне кажется, что в stl сделали выбор в пользу беззнаковых типов потому что итерация ими больше походит на итерацию указателями и итераторами.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[22]: встречный ликбез.
От: Erop Россия  
Дата: 17.11.06 12:49
Оценка:
Здравствуйте, Erlond, Вы писали:

E>Бывают, я же не говорил, что их не бывает. Я привёл конкретный пример с типами int и unsigned int. И задал по нему вполне конкретный вопрос.

E>Здесь идёт разговор о целых знаковых и целых беззнаковых числах, числа с плавающей запятой выходят за рамки этой дискуссии, т.к. они не являются целыми и т.к. они всегда знаковые

Собственно для тех участников обсуждения, ктьо не знает всех подрбностей.
Весь сыр-бор происходит от того, что аппаратура вольна представлять знаковые целые числа как ей заблагорассудится.
И стандарт С++ не навязывает ей двоичного-дополнительного кода.
Так что бывают реализации С++, в которых int реализован как бит занака и unsigned мантиса. Увы.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[26]: А может всё-таки ответ, а не мантру?
От: Erop Россия  
Дата: 17.11.06 12:55
Оценка:
Здравствуйте, saproj, Вы писали:

E>>Так всё-таки ответ на вопрос "почему лучше" будет каким? )


S>Все уже сказано. Мною в последней строке этого
Автор: saproj
Дата: 16.11.06
сообщения. Другими людьми тоже сказано не раз. Обрати внимание как терпеливо и подробно объясняет Андрей Тарасевич. Не лишне будет еще раз сосредоточенно прочитать.


То есть ответ такой: "потому, что использование типа int для числа деталей менее понятно, чем использование unsigned int"?

А если расшифровать, что каждый из типов обозначает в языке C++, он выглядит совсем уж чуднО: "Потому, что использование знаковой арифметики, не позволяющей работать с числами сильно превышающими миллиард для работы с количеством деталей менее понятно, чем использование арифметики по модулю 0х1000000"?

Это вот утверждение можно как-то аргументировать? Или это какое-то изотерическое атомарное знание?

Андрей очень много и часто содержательно пишет, но совсем не про это, а про что-то другое.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[23]: встречный ликбез.
От: Erlond Россия  
Дата: 17.11.06 12:56
Оценка:
Здравствуйте, Erop, Вы писали:

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


E>>Бывают, я же не говорил, что их не бывает. Я привёл конкретный пример с типами int и unsigned int. И задал по нему вполне конкретный вопрос.

E>>Здесь идёт разговор о целых знаковых и целых беззнаковых числах, числа с плавающей запятой выходят за рамки этой дискуссии, т.к. они не являются целыми и т.к. они всегда знаковые

E>Собственно для тех участников обсуждения, ктьо не знает всех подрбностей.

E>Весь сыр-бор происходит от того, что аппаратура вольна представлять знаковые целые числа как ей заблагорассудится.
E>И стандарт С++ не навязывает ей двоичного-дополнительного кода.
E>Так что бывают реализации С++, в которых int реализован как бит занака и unsigned мантиса. Увы.

А на каких платформах?
Re: Предложение
От: Erop Россия  
Дата: 17.11.06 13:07
Оценка:
Народ!
Для людей, которым так нравится слово unsigned написанное не в комментарии к методу, а в имени типа возвращаемого значения я предлагаю поступать так:

typedef int int_for_unsigned_values;


И читабельно всё станет и совместимо и вообще со всех сторон прекрасно.

Для совсем уж пуристов его можно сделать не typedef, а enum со своими операторами. Скажем так:

enum int_for_unsigned_values{ int_for_unsigned_values_min = INT_MIN, int_for_unsigned_values_max = INT_MAX };
inline int_for_unsigned_values opearator + ( int_for_unsigned_values left, int_for_unsigned_values right )
{
    return static_cast<int_for_unsigned_values>( left + right);
}

Ну и т. д.

Можно даже assert'ом проверять, что всё было и осталось положительным.

и будет всем счастье
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[24]: встречный ликбез.
От: Erop Россия  
Дата: 17.11.06 13:11
Оценка:
Здравствуйте, Erlond, Вы писали:

E>А на каких платформах?


На маргинальных, к счастью. Всякая встраиваемая гадость.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[16]: Видимо ошибка в кончерватории :)
От: Erop Россия  
Дата: 17.11.06 14:42
Оценка:
Здравствуйте, Erlond, Вы писали:


E>Мне кажется не разумно использовать знаковый тип данных для тех величин, которые не должны стать отрицательными.


Ради чего?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Нужен ли unsigned
От: Максим2006 Беларусь  
Дата: 17.11.06 16:01
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Максим2006, Вы писали:


М>>Было бы лучше иметь два разных типа — один для модульной арифметики, а второй — для беззнаковой (с UB при выходе за границы и иными правилами преобразования)


К>Модулярная арифметика может трактоваться как частный случай UB Так что unsigned замечательно справляется с обеими ролями.


Допустим, что модулярная арифметика — это частный случай UB А как насчёт других правил преобразования типа?

4.7/2 If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source
integer (modulo 2n where n is the number of bits used to represent the unsigned type). [Note: In a two’s
complement representation, this conversion is conceptual and there is no change in the bit pattern (if there
is no truncation). ]

Это даёт право на выражение "unsigned i = -1;" и любые преобразования int в unsigned
В общем, хотелось бы иметь тип (или модификатор), который обезопасил бы от подобных преобразований (о которых уже многие тут
Автор: remark
Дата: 14.11.06
говорили)
Re[3]: Безумью храбрых...
От: Vain Россия google.ru
Дата: 17.11.06 16:16
Оценка:
Здравствуйте, Erop, Вы писали:

E>Прекрасный, надёжный способ сделать неотлаживаемую программу, которая в релизе и дебаге гарантированно ведёт себя по-разному!!!

Если код неправильный (!) — то по-разному

E>Не поделишься зачем это надо?

чтобы использовать usigned и чтобы в дебуге править все неоднозначные вырнинги..
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[2]: Нужен ли unsigned
От: Аноним  
Дата: 17.11.06 19:09
Оценка:
Ш>В моём коде чаще всего используются беззнаковые переменные, чем знаковые.
А в моем наоборот. У тебя же примеры задействуют только unsigned и unsigned. А что будешь делать если будет необходимо смешать с обычным int-ом или double-ом? О чем тут народ и толкует. Например передать в какую-нибудь [библиотечную] функцию.

Ш>1) Беззнаковая арифметика имеет точно определённую семантику, в отличии от знаковой.

Ты о чем это?

Ш>2) В беззнаковой арифметике лего ловить переполнение.


Ш>
Ш>unsigned a=...;   
Ш>unsigned b=...;

Ш>a+=b;

Ш>if( a<b ) 
Ш>  { //overflow  
Ш>   ... 
Ш>  }
Ш>

Ты думаешь я аналогичный код не смогу написать для знаковых переменных? Кстати, ты проверяешь на переполнение уже после того как оно случилось. Надо бы проверять раньше, чтобы не допустить переменной принять invalid state.

Ш>3) В C/C++ размерности массивов выражаются беззнаковым типом size_t. По этой причине ипользовать для индексирования знаковые типы -- создавать потенциальные дыры.

Ну очень сложная арифметика нужна для индексирования массивов! Дай пример где реально нужны unsigned и где signed просто нельзя использовать.

Ш>4) LUT удобнее делать с беззнаковыми типами. Классический пример.

Левый пример какой-то.

Ш>
Ш>bool CharIsXXX(char c)
Ш> {
Ш>  static const bool table[256]={...};

Ш>  return table[(unsigned char)c];
Ш> }

Ш>

1) Почему бы уж саму с не объявить беззнаковой вместо того, что приводить ее позднее?
2) Если в функцию передается отрицательное с, то твой каст "выправляет" невалидное значение в валидное, и ни вызывающая функция и ни сама не вызываемая так и не узнают что произошло что-то не так. Имхо тут было бы правильнее проверить не является ли с меньше нуля, вернуть сразу ложь (или вообще изменить возвращаемый тип чтобы позволить сигнализировать об ошибке).

Вообще, Шахтер, Андрей Тарасевич и Ко, может объясните почему тогда стандартом не предусмотренны беззнаковые числа с плавающей точкой? И ни одна архитектура не поддерживает таких чисел насколько я знаю. Ведь беззнаковые числа имеют столько преимуществ над знаковыми!
Re[18]: Видимо ошибка в кончерватории :)
От: Erop Россия  
Дата: 18.11.06 07:23
Оценка:
Здравствуйте, Erlond, Вы писали:

E>А в чём, собственно, вопрос?


В чём состоит практическая выгода unsigned типов? Вот в чём практические потери и трудности я подробно разъяснил. А в чём таки состоит выгода --
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: О чём это
От: Erop Россия  
Дата: 18.11.06 07:31
Оценка:
Здравствуйте, Аноним, Вы писали:

Ш>>1) Беззнаковая арифметика имеет точно определённую семантику, в отличии от знаковой.

А>Ты о чем это?

Насколько я могу предпологать то, вот о чём:
В стандарте C++ принят следующий компромис:
1) unsigned числа должны быть такими, к каким мы все привыкли. А вот числа со знаком могут быть любыми, на усмотрение авторов аппаратуры.
Поэтому не извесно что будет если
1) в арифметике со хнаком произойдёт переполнение
2) как работает преобразование из знаковых в беззнаковые и обратно, если значение не представимо в обоих типах.
3) Что будет если ты выполнишь ряд операций с отрицательным значением (деление, взятие отатка, сдвиг и т. д.)
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: МСМ
От: Erop Россия  
Дата: 18.11.06 07:37
Оценка:
Здравствуйте, Erop, Вы писали:

Собственно далее следует моё скромное мнение на эти обстоятельства

E>В стандарте C++ принят следующий компромис:

E>1) unsigned числа должны быть такими, к каким мы все привыкли. А вот числа со знаком могут быть любыми, на усмотрение авторов аппаратуры.
Тем не менее числа int обычно всё-таки хорошо представляют именно не очень большие целые числа, так что они, как ни странно являются более высокоуровневыми.

E>Поэтому не извесно что будет если

E>1) в арифметике со хнаком произойдёт переполнение
Ну просто нужно стараться программировать так, чтобы переполнения не происходило. В случае переполнения писать assert. Так что даже если произойдёт аппаратное исключение -- ничего грандиозно другого не случится. Миримся же мы в конце концов с анологичным поведением типа double

E>2) как работает преобразование из знаковых в беззнаковые и обратно, если значение не представимо в обоих типах.

Ну просто не надо, по возможности, пользоваться этим преобразованием.

E>3) Что будет если ты выполнишь ряд операций с отрицательным значением (деление, взятие отатка, сдвиг и т. д.)

Ну это вообще не имеет отношения к проблеме типа значения. Если вам нужно выполнить такую операцию с отрицательными числами, то в С++ это одинаково нельзя сделать не через int не через unsigned int
Всё равно прийдётся писать какой-то хитрый код.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: Егоизвращённые желания
От: Erop Россия  
Дата: 18.11.06 07:44
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Ну здрасьте? "Число" — математическая абстракция. Само "число" невозможно "получить". Его даже вообразить тольком нельзя. Все "числа", котрые мы можем получить, увидеть, потрогать или, скажем, понюхать — это на самом деле не "числа", а разнообразные представления чисел. Вариантов представлений много и дополнителный код — лишь один из них. И какой-то вариант в любом случае равно придется выбирать. А "просто -2 число такое" — так не бывает.


Ну то есть ты предлагаешь вообще все вычисления производить в unsigned?
Типа интерпритировтаь его как signed в доп. коде и радоваться? Всё равно ведь "0xFFFE" и "-2" якобы отличить нельзя?

ИМХО ты переизвратил мои извращённые желания Уважаю! Ты настоящий извращенец!


Что касается проблем с "воображением чисел".

Вообще языки высокого уровня нужны как раз для того, чтобы изолировать предметную область от слишком тонких подробностей реализации.
В конце концов и числа double не бывает. Бывают биты. И оператора if тоже не бывает и т. п.

Просто когда ты решаешь сложную задачу. Скажем организуешь какой-то сверхоптимизированный перебор чего-то. Скажем шахматной партии.
И оцениваешь варианты с качеством "сколько шансов из 10000 на победу", которое меняется от 0 до 10000. То тебе лучше бы сконцентировать своё внимание на формулах и числах, а не на дополнительном двоичном коде.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Танковые клинья наступают...
От: Erop Россия  
Дата: 18.11.06 08:05
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

E>>
E>>typedef int int_for_unsigned_values;
E>>

E>>И читабельно всё станет и совместимо и вообще со всех сторон прекрасно.

АТ>Совет, по своей сути примерно эквиватентный предложенному в соседнем сообщении варианту с различными типами в DEBUG и не DEBUG ("Безумью храбрых" и т.п.)


Это ещё почему? В "безумии храбрых" предлагали намеренно сделать поведение debug и release версий очень сложно различным. При этом не очень понятно за ради чего. Например, если бы мой сотрудник так поступил, я бы поставил вопрос о преднамеренном саботаже.

А я предлагаю бороться с теми "ужасными" проблемами, которые влечёт использование signed для значений, которые не могут быть по семантике отрицательными, намного прямее. На языке С++

Казалось бы, что тут такого необычного?
Вот когда тебе нужно число с плавающей точчкой ты же пишешь что-то типа fixed_number<10>?


Для экипажей танковой колонны разъясняю:

Я конечно утрировал. Мне кажется что проблема вообще не стоит выеденного яйца. Но signed типы приводят в случае работы просто с небольшими целыми числами к намного более простому и надёжному коду. И, как ни стринно, более переносимому. Так что попытки использовать, по идеологическим причинам (скажем ради спорной читабельности) при работе с числами unsigned типы, я воспринимаю как преднамеренное запутывание кода.

Короче выгоды от unsigned сомнительн и спорны, проблемы с использование int для представления числа апельсинов у Буратино надуманны, ИМХО, так что надо пользоваться int и всё.
Ну а если все вокруг столь странные люди, что без специального типа не могут понять, что у Буратино не должно оказаться -8 яблок, и комментарий с assert им тоже не помогают, то можно завести int_for_unsigned_values.

проблема только в том, что любой вменяемый программист понимает, что ради такой ерунды разводить новый тип не надо.

Ну так вот и объясните мне теперь, а почему же переходить к int_for_unsigned_values не надо, а к unsigned int надо?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[20]: Давай немного подробнее?
От: Erop Россия  
Дата: 18.11.06 09:51
Оценка:
Здравствуйте, Erlond, Вы писали:

E>Для меня "выгоды" состоят в следущем:

Спасибо за ответ!
Ты первый человек в этом обсуждении, кто решился таки понятно перечислить что нравится.
Увы, мне это всё не совсем кажется выгодами


E>1. Не вижу смысла использоваться знаковые целые для величин, которые не будут отрицательными -> дополнительная информация тому, кто будет использовать код

Это вообще не выгода Выгода, это когда ты что-то получаешь. Я так понял, что тебе слово unsigned в имени типа ближе роднее и понятнее, чем, например, комментарий. Видимо то, что слово unsigned в С++ обозначает нечто очень своеобразное и совсем другое (модульная арифметика, тоо сё) тебе не важно.
Но почему тогда не делать как-то прямо. Например так
Автор: Erop
Дата: 17.11.06
?
Опять же, смотри. И читабельно, и модульной арифметики не надо и в debug-версии есть где assert'ы (в варианте с enum) написать.

E>2. Т.к. нет отрицательных значений убирается проверка на то, что значение выскочило "ниже" положенного. То, что удобно ловить ошибки по отрицательным — не соглашусь, ошибку нужно ловить перед выполнением операции.

А в чём смысл? Идея в том, что так эффективнее или в чём-то ещё?
Опять же тут есть такая беда, что часто число плохо ограничено сверху. Ну скажем число апельсинов. Вот я там складывал что-то вычитал, как потом написать assert, чтор всё хорошо получилось?

Ну а что касается проверок до, а не после, то я согласен совершенно, но не понимаю чем тут unsigned типы-то помогают? Вот такой подход
Автор: Erop
Дата: 17.11.06
помог бы, да. А unsigned-то тут какой помошник?

E>3. Если в коде с беззнаковой арифметикой содержится ошибка, то она очень быстро даст о себе знать, в отличие от знаковой, на которой до поры, до времени всё будет работать, а когда ошибка даст о себе знать, то тогда уже может понадобиться ни день, и не два на отладку. Вполне возможно, что всё будет работать до самого релиза. Статья на тему
Автор(ы): Dr. Joseph M. Newcomer
Дата: 18.06.2001
Статья посвящена проблемам перехода с Debug-версии на Release-версию. Рассматриваются
типичные ошибки, которые могут не проявляться в отладочной версии, но проявляются в финальной.
Обсуждается вопрос "ошибок компилятора" и вопросы необходимости оптимизации и ее побочные эффекты.
В последней редакции добавлен раздел посвященный проблеме совместимости динамических библиотек.


Юмор состоит в том, что вполне возможно, что будет работать и вообще до скончания веков
Я согласен, что программирование с unsigned типами тербует от программиста больше работы, выявляет больше ошибок и в результате получается тот же результат. Но вот за ради чего? почему "больше работы с тем же результатом" -- это выгода?

Вот смотри, есть два куска кода:

for( int i = count - 1; i >= 0; i-- )
    do_somthing( i );

и
unsigned int i = count;
while( i > 0 ) {
    i--;
    do_somthing( i );
}


Вот если бы второй был "правильным", а первый "неправильнвм", то да. Такой подхд бы был верным. Не спорю. Но ведь они оба правильные. Просто во втором проще ошибиться

Так что я не совсем понял что ты имеешь в виду под третьей выгодой


Кстати, что касется "статьи на тему", то я там слово "unsigned" нашёл только вот в таком абзаце:

Вы обязаны возвращать значение и должны передавать параметры, как указано (и вы обязаны использовать типы WPARAM и LPARAM, если вам нужна совместимость с 64-битным миром; определенное количество людей, "знавших", что WPARAM означает WORD и просто писавших (WORD, LONG) в своем коде под Win16, расплачивались при попытке перейти на Win32, где это, в действительности, (UNSIGNED LONG, LONG). И все опять будет иначе в Win64. Так зачем делать неправильно, пытаясь показаться умным?).

Вроде как тут вообще про разные версии Win API человек пишет. И тема знаковости/беззанковости и что лучше/хуже вообще не раскрыта
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Танковые клинья наступают...
От: Erlond Россия  
Дата: 18.11.06 09:56
Оценка:
Тонкий намёк на выражение "для тех, кто в танке"
Re[5]: Танковые клинья наступают...
От: Erop Россия  
Дата: 18.11.06 09:59
Оценка:
Здравствуйте, Erlond, Вы писали:

E>Тонкий намёк на выражение "для тех, кто в танке"


Ну тут есть мода давать всякие советы и разъяснения не активным участникам дискуссии, а тем, кто пытается хоть как-то въехать в обсуждаемую тему.

Мы тут жжём все конечно, но понятноможет быть и не всем.
Ну а так как народу много, то одного танка на всех однозначно не хватит
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[22]: Давай немного подробнее?
От: Erop Россия  
Дата: 21.11.06 15:13
Оценка:
Здравствуйте, Erlond, Вы писали:


E>По поводу typedef int int_for_unsigned_values это уже перебор. Обсуждается не само слово unsigned, а тип данных и модульная арифметика. Мне кажется, что данная "шутка юмора" здесь неуместна.

E>

E>Опять же тут есть такая беда, что часто число плохо ограничено сверху. Ну скажем число апельсинов. Вот я там складывал что-то вычитал, как потом написать assert, чтор всё хорошо получилось?


E>Очень просто, если при сложении получилось число меньшее, чем каждое из слагаемых — переполнение, аналогично для вычитатния — если результат больше, чем числа, учавствовавшие в вычитании — переполнение.


Ну тогда лучше завести enum int_for_unsigned_values и переопределить для него операции, с проверками. Разве это не более прямой и надёжный способ?

E>

E>Вот смотри, есть два куска кода:

E>>

E>>for( int i = count - 1; i >= 0; i-- )
E>>    do_somthing( i );
E>>

E>>и
E>>
E>>unsigned int i = count;
E>>while( i > 0 ) {
E>>    i--;
E>>    do_somthing( i );
E>>}
E>>


E>
E>unsigned int i = 0;

E>while( i < count )
E> {
E>    ++i;
E>    do_somthing( i );
E>}
E>


1) Твой код не эквивалентен моему
У меня массив итерируется с конца в начало! А вдруг мне надо именно так?
Вот при знаковом i всё равно куда и с каким шагом итерировать, а вот с unsigned начинаются косяки и двери

E>Кстатии, если не имеет значения будет ли выполнен постфиксный или префиксный инкремент (декремент), то лучше использовать префексный, т.к. не создаётся временного объекта, это связно с особенностью реализации этих операций.

Кстати, любой совсременный вменяемый компилятор скомпилирует и для int i и для unsigned int i обе формы инкремента в один и тот же код

E>По поводу статьи , я просто хотел сказать, что то, что работало на дебаге, может разчъехаться на релизе, тем более, если код с ошибкой, которая пока проезжает.


Ну так объясни какая же ошибка, которая может вылезти на релизе содердится в коде с signed i?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: У синьора есть опыт?
От: Erop Россия  
Дата: 21.11.06 15:18
Оценка:
Здравствуйте, Erlond, Вы писали:


E>

E>Теперь предлагаю посмотреть на это дело с другой стороны.
E>В конце концов переносимость C++ программ -- это миф.
E>Попробуйте написать сложную программу, которая легко переживёт перенос на платформу сильно другой разрядности. Скажем из 32-бит в 16?
E>Нифига у вас не выйдет. Всё равно переполнения будут вас преследовать и всякие другие проблемы.


E>Ну почему же миф? Всё вполне реально. Просто не нужно в коде использовать константы, указывающие размеры типов данных, всё определять через sizeof, а сами типы данных привести в соответствие с размером слова целевой платформы, т.е. int — 16 бит, и т.д.



У месье есть опыт или это теоритическое изыскание?


Вот представь себе, что ты пишешь текстовый редактор. Который редактирует текст на диске.
И используешь int (или даже unsigned int) для номера строки.

Ну и вот на 32-битной платформе всё у тебя будет хорошо, а вот на 16-битной уже веселее всё станет, потому что реально встретить файл на 100 000 строк

А вот на 8-битной или на 12-битной платформе вообще туго прийдётся.

Или у месье таки есть опыт?


Вот мой опыт говорит о том, что какую кросплатформенную разработку не возьмёшь, там всюду ifdef на ifdefe сидит и им же погоняет
К чему бы это, если всё так мегапереносимо?

Для сравнения советую посмотреть прогу какую-нибудь на фортране, например
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: мои измышления про unsigned, size_t и стандарт
От: Erop Россия  
Дата: 21.11.06 15:55
Оценка:
Джони!
Если ты не согласен с тем, что беззнаковый size_t -- это неизбежное следствие совместимсти с подобными платформами, то поделись аргументами!
Правда очень интересно
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: У синьора есть опыт?
От: Erlond Россия  
Дата: 21.11.06 16:52
Оценка:
E>Вот представь себе, что ты пишешь текстовый редактор. Который редактирует текст на диске.
E>И используешь int (или даже unsigned int) для номера строки.

E>Ну и вот на 32-битной платформе всё у тебя будет хорошо, а вот на 16-битной уже веселее всё станет, потому что реально встретить файл на 100 000 строк


E>А вот на 8-битной или на 12-битной платформе вообще туго прийдётся.


E>Или у месье таки есть опыт?



E>Вот мой опыт говорит о том, что какую кросплатформенную разработку не возьмёшь, там всюду ifdef на ifdefe сидит и им же погоняет

E>К чему бы это, если всё так мегапереносимо?

E>Для сравнения советую посмотреть прогу какую-нибудь на фортране, например


Я лично такие проекты не писал, однако у нас в городе Севастополе есть предприятие, "Таврида Электрик", которое программирует микроконтроллеры, в том числе и на С++. И ничего, живут программы. Естественно, проект требуется подредактировать. Однако, это не так страшно, как кажется. Все используемы типы данных определяются через typedef, а все платформенно-зависимые константы макросами. После корректировки этих величин под целевую платформу, получаем живущий проект.

>Ну и вот на 32-битной платформе всё у тебя будет хорошо, а вот на 16-битной уже веселее всё станет, потому что реально встретить файл на 100 000 строк


А что мешает ввести проверку? Вводишь условие, что в файле должно быть не больше UINT_MAX строк (или INT_MAX). Для 32-битной платформы это будет 2^32 -1, а для 16-ти битной 2^16-1.
Re[7]: мои измышления про unsigned, size_t и стандарт
От: johny5 Новая Зеландия
Дата: 22.11.06 16:01
Оценка:
Здравствуйте, Erop, Вы писали:

E>Джони!

E>Если ты не согласен с тем, что беззнаковый size_t -- это неизбежное следствие совместимсти с подобными платформами, то поделись аргументами!
E>Правда очень интересно


Просто не хотел явно вмешиваться в ваш разговор. -1 это за переносимость. Люди спокойно работают пишут портируемый код (используя int32_t, uint32_t) а вы вдруг заявили что бах! нет этого кода. И люди, целые компании, растворяются в воздухе..
Таким образом я просто был вынужден выразить своё несогласие..

К сожалению вашей мыслью о связи size_t и слабых платформ не проникся, потому что ничего не понял.

А по поводу топика..


при избегании подобного рода ошибок, использование unsigned оправдано в тех случаях, когда вы декларируете что значение переменной ни при каких обстоятельствах не может быть меньше нуля — вам не придётся проверять это дополнительно. Так сделано в STL для size() — это спорно, но, как я ранее в этой ветке писал, я понял что удобно проверять индекс например вот так
if( (size_t)i < var.size() ) ... //значит мы можем использовать var[i]


Конечно, если я могу переобъявить переменную, я объявлю её size_t

Благо, хороший компилятор, понимая актуальность подобных проблем, выдаёт много разных warning-ов и, в runtime, анализирует представимость результата при неявных преобразованиях типа.
Re[10]: Егоизвращённые желания
От: johny5 Новая Зеландия
Дата: 22.11.06 16:09
Оценка:
E>Вообще языки высокого уровня

C/C++ относятся к языкам низкого уровня. Дальше — asm
Re[8]: про переносимость С++ и прочее
От: Erop Россия  
Дата: 22.11.06 17:52
Оценка:
Здравствуйте, johny5, Вы писали:

J>Просто не хотел явно вмешиваться в ваш разговор. -1 это за переносимость. Люди спокойно работают пишут портируемый код (используя int32_t, uint32_t) а вы вдруг заявили что бах! нет этого кода. И люди, целые компании, растворяются в воздухе..

J>Таким образом я просто был вынужден выразить своё несогласие..

Обращаю твоё внимание, что ни int32_t ни uint32_t в стандарте вроде как нет
Кроме того, я вовсе не говорил, что на C++ невозможно написать переносимый и кросплатформенный код. Я говорил совсем о другом.
Что переносимость, как это понимается в стандарте, недостижима. Ну то есть чтобы вот взяли, написали и везеде работает.
Это только в довольно простых программах бывает. А в непростых и архитектуру учесть ради производительности приходится и разрядность платформы и возможности системы по работе с памятью и много чего ещё. Так что какую большую прогу не возьми -- толпы ifdef насованы, ради каждой платформы.

Ещё раз призываю сравнить с FORTRAN, например.


J>К сожалению вашей мыслью о связи size_t и слабых платформ не проникся, потому что ничего не понял.
Ну вот смотри.
Пусть у нас какой-то 16-битный компик. Скажем типа БК-0010, кажется так его звали. Только ROM мало, а RAM много. Скажем 4 против 60 килобайт. И мы можем завести объект размером в 40 кило скажем. Как его размер представлялся бы в signed int? Так что куда не денешься -- а приходится брать unsigned тип для size_t и для размера вектора.

С другой стороны если ты попробуешь перенести какую-то прогу тех самых контор, с int32_t на такой компик, то ты много-много гемора огребёшь!
Так что никакого реального выигрыша от того, что size_t "переносим" в смысле стандарта C++ при реальном переносе получить не удаётся.


J>
J>при избегании подобного рода ошибок, использование unsigned оправдано в тех случаях, когда вы декларируете что значение переменной ни при каких обстоятельствах не может быть меньше нуля — вам не придётся проверять это дополнительно. Так сделано в STL для size() — это спорно, но, как я ранее в этой ветке писал, я понял что удобно проверять индекс например вот так

J>
J>if( (size_t)i < var.size() ) ... //значит мы можем использовать var[i]
J>


1) если i таки может быть < 0, то этот код вообще UB. О какой вообще переносимости тут речь?

J>Конечно, если я могу переобъявить переменную, я объявлю её size_t

Ну и будет неудобно. Так как индекс в массиве легко может участвовать в вычитании. Например при итерации массива с конца в начало.

J>Благо, хороший компилятор, понимая актуальность подобных проблем, выдаёт много разных warning-ов и, в runtime, анализирует представимость результата при неявных преобразованиях типа.


И что происходит дальше? Авост?
На кой себе так переусложнять жизнь?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: про переносимость С++ и прочее
От: MaximE Великобритания  
Дата: 23.11.06 11:16
Оценка:
Здравствуйте, Erop, Вы писали:

J>>Просто не хотел явно вмешиваться в ваш разговор. -1 это за переносимость. Люди спокойно работают пишут портируемый код (используя int32_t, uint32_t) а вы вдруг заявили что бах! нет этого кода. И люди, целые компании, растворяются в воздухе..

J>>Таким образом я просто был вынужден выразить своё несогласие..

E>Обращаю твоё внимание, что ни int32_t ни uint32_t в стандарте вроде как нет


The New C Standard

5.2.4.2.1 Sizes of integer types limits.h

Additional limits are specified in <stdint.h>.

Commentary

This header contains declarations of integer types having specified widths, along with corresponding limits macros.

C90
Support for these limits and the header that contains them is new in C99.

C++
Support for these limits and the header that contains them is new in C99 and is not available in C++.

Re[10]: У всех свои цели :)
От: Erop Россия  
Дата: 24.11.06 09:51
Оценка:
Здравствуйте, johny5, Вы писали:

J> А тут не верно. int32_t он на то и 32 что на всех платформах 32х битный целочисленный и переносимость будет 100%.

J> Конечно если на 16 битной машине нет 32х битных чисел вообще, то реализовать такой тип — придётся потрудиться. Главная цель — портируемость.

Ну если твоя цель написать прогу которая компилируется, или запускается, то да
А вот если чтобы работала и при этом хорошо (без тормозов, перерасхода ресурсов, органично для целевой платформы и надежно), то все эти ужимки тебе не помогут



J>Моё ИМХО: выбор signed/unsigned типа — решение проектировщика — это, я понимаю, высокий (абстрактный) уровень. Тут не учитываются детали имплементации а только декларируется соглашение API о принимаемых/возвращаемых значениях. В данном случае вы предоставляете "барьер", человек, предоставляющий unsigned значение должен удостовериться что он предоставляет его правильно, соответственно API может быть спокойна за знаковость значения и наоборот.

Вот если бы ещё правила С++ это всё позволяли...
Ещё раз спрошу: "от чего бы такие ограничения не наложть прямо
Автор: Erop
Дата: 17.11.06
?" Зачем химичить с модульной арифметикой?


J>А неумение программиста работать с unsigned типом и вообще пренебрежение низкоуровневыми деталями, которые предоставляет язык — это уже совсем другая проблема и лечиться она повышением квалификации програмиста, повышением уровня warning-ов + концепция warning -> error, административными методами. В крайнем случае, можно сменить язык на более высокоуровневый, например на ваш FORTRAN.

обычно смотрят в сторону нет или явы
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[23]: встречный ликбез.
От: dr.Chaos Россия Украшения HandMade
Дата: 14.12.06 10:43
Оценка:
Здравствуйте, Erop, Вы писали:

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


E>>Бывают, я же не говорил, что их не бывает. Я привёл конкретный пример с типами int и unsigned int. И задал по нему вполне конкретный вопрос.

E>>Здесь идёт разговор о целых знаковых и целых беззнаковых числах, числа с плавающей запятой выходят за рамки этой дискуссии, т.к. они не являются целыми и т.к. они всегда знаковые

E>Собственно для тех участников обсуждения, ктьо не знает всех подрбностей.

E>Весь сыр-бор происходит от того, что аппаратура вольна представлять знаковые целые числа как ей заблагорассудится.
E>И стандарт С++ не навязывает ей двоичного-дополнительного кода.
E>Так что бывают реализации С++, в которых int реализован как бит занака и unsigned мантиса. Увы.

Нет сыр бор был в том что опасно использовать unsigned . Андрей сказал, что не опасно и просто требует большей внимательности. Если ты пишешь под какую-то конкретную платформу, то не знать ее особенности просто преступление .
Если пишется изначально переносимый код, то написать обертку не так сложно, а вещи зависимые от конкретной платформы будут в одном месте, что станет вполне управляемо.

Если у нас будут большие числа и серьезные вычисления над ними, тут надо брать большую разрядность или опять же писать свою обертку.

По поводу хранения величин по смыслу unsigned в signed, это правда толком ничего не дает, хотя я думаю это стоит отнести к вопросам стиля. А все вопросы связанные со стилем это уже СВ .

Но полагаю, что при использовании unsigned все таки нет UB, т.к. он одинаково представляется на всех платформах. Да и он правда заставляет быть более внимательным.

Можно провести аналогию с исключениями, т.к. они требуют значительно больше внимания чем коды возврата, но и дают тоже больше гарантий.
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Re[6]: мои измышления про unsigned, size_t и стандарт
От: dr.Chaos Россия Украшения HandMade
Дата: 14.12.06 11:19
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, night beast, Вы писали:


NB>>По поводу Страуструпа. Если бы все было так однозначно, то vector::size_type был бы интом.


E>Собственно я подумал и понял почему ни size_t, ни размер std::vector, ни его индекс не могут быть в С/С++ знаковым типом.

E>Это всё происходит из-за так называемой совместимости.

E>Действительно, никто не запрещает в C++ иметь очень большие объекты. Напимер объект размером почти со всю адресуемую память. Или vector.

E>Мало того, такие реализации наверняка были, когда компьютеры были слабее ZX Spectrum. Не пресоналки, а реальные такие компьютеры. Большие-пребольшие.

E>Так что если мы хотим сформулировать стандарт языка, который будет описывать и такие архитектуры, мы просто не можем выбрать другой тип, кроме unsigned


Дело не только в диапазоне, но и в отсутствии UB. Т.е. правильно написанная итерация будет работать правильно на всех платформах.

Ты причину верно указал, только пример не очень привел .

E>В некотором смысле это просто следствие того, как было принято делать компьютеры. Только и всего.

А как их было принято делать?
E>

E>Теперь предлагаю посмотреть на это дело с другой стороны.
E>В конце концов переносимость C++ программ -- это миф.
E>Попробуйте написать сложную программу, которая легко переживёт перенос на платформу сильно другой разрядности. Скажем из 32-бит в 16?

Если изначально был такой переход задуман, то довольно легко. Если нет, то это будет очень кроваво.
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Re[24]: Ещё раз о галвном :)
От: Erop Россия  
Дата: 14.12.06 12:10
Оценка:
Здравствуйте, dr.Chaos, Вы писали:

DC>По поводу хранения величин по смыслу unsigned в signed, это правда толком ничего не дает, хотя я думаю это стоит отнести к вопросам стиля. А все вопросы связанные со стилем это уже СВ .

DC>Но полагаю, что при использовании unsigned все таки нет UB, т.к. он одинаково представляется на всех платформах. Да и он правда заставляет быть более внимательным.

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

При этом у signed для хранения именно чисел остаётся то приимущество, что труднее переполнить по вычитанию. Ну и вообще assert'ы писать проще, циклы вские.
Всё-таки цикл for устроен так, что для того чтобы он кончился, его параметр должен принять невалидное значение

А если вам таки нужны опасные операции с отрицательными целыми числами (/ % << >>), то вам unsigned тут точно не помошник
Помошник тут приведение к положительным, вычисление, а потом соответсвующая смена знака.
Вывод: числа всегда лучше хранить в signed числах, но можно приделать обёртку (если это действительно нужно), которая правильно вычисялет подобные операции.

Вот у нас, например, есть функции round, ceil и floor, которые делят, округляя в нужную сторону. Правда нет округлялки к 0. Но это потому, что она "так и не приг-Г-Г-годилась"

DC>Можно провести аналогию с исключениями, т.к. они требуют значительно больше внимания чем коды возврата, но и дают тоже больше гарантий.


Ну вот, ИМХО, эта анология ложная, так как unsigned не то что дают какие-то гарантии, а наоборот, в тех случаях, когда у signed возможны проблемы, гарантирует проблемы в любом случае, при преобразованиях между signed и unsigned арифметикой
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: мои измышления про unsigned, size_t и стандарт
От: Erop Россия  
Дата: 14.12.06 15:09
Оценка:
Здравствуйте, dr.Chaos, Вы писали:

DC>Дело не только в диапазоне, но и в отсутствии UB. Т.е. правильно написанная итерация будет работать правильно на всех платформах.

Странно. Объясни мне, где UB, например, в таком вот коде:
double sum = 0.0;
for( int i = array.size() - 1; i >= 0; i -= step ) {
    sum += array[i];
}


Казалось бы UB случается, когда мы переходим signed<->unsigned на значениях, не помещающихся в оба типа и ещё есть зависимость от реализации при некоторых (не самых нужных обычно) операциях над отрицательными числами.
При сложении/вычитании без переполнения никакого UB нет!

E>>В некотором смысле это просто следствие того, как было принято делать компьютеры. Только и всего.

DC>А как их было принято делать?
Ну были компы, у которых памяти было мало и можно было родить объект на всю почти память, например.
E>>

E>>Попробуйте написать сложную программу, которая легко переживёт перенос на платформу сильно другой разрядности. Скажем из 32-бит в 16?

DC>Если изначально был такой переход задуман, то довольно легко. Если нет, то это будет очень кроваво.

Ну если изначально писать под несколько платформ, то почти любой язык в каком-то смысле переносим
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[26]: Ещё раз о галвном :)
От: Erop Россия  
Дата: 14.12.06 15:21
Оценка:
Здравствуйте, dr.Chaos, Вы писали:

DC>Портируемость С++ ты видимо не верно понимаешь . Она говорит о том что стандартная библиотека будет работать на разных платформах одинаково, а то что ты написал, это уж извини как написал так и работает .


Ну я понимаю просто. Вот написал я прогу для Win, а кастомеры говорят: "Хотим и под Mac OS!"
Вопрос: "сколько будет стоить перенос"
Короче в практическо-управленческом ключе

DC>Использование беззнаковых делает человека более внимательным, а это уже плюс.

Ну в принципе так можно поступать всегда, тогда будешь аскетом.
Например можно ездить не на удобной иномарке а на очень старой "копейке". Тоже не будет давать слишком сильно лихачить
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: offtopic
От: Ulfur Россия  
Дата: 14.12.06 15:54
Оценка:
Здравствуйте, Erop, Вы писали:

E> [...]


Читал Ваши рассуждения о переносе программ на другие платформы... У меня был опыт переноса части программы с 32-х битной платформы на 16-и битную, причем довольно широко использовались вычисления с целыми числами. Если Вам или кому-то еще будет интересно — прошу посмотреть
Автор: Ulfur
Дата: 31.10.06
— то, что я уже пытался безуспешно обсудить со здешними форумчанами
В конечном счете именно С++ (на С мой подход по естественным причинам не повторить) позволил избежать ряда грубых ошибок и падений — ценой производительности, но только в отладочной сборке.

Если нужно будет оградить себя любой ценой от переполнений, то опять же проблему можно решить средствами С++ (естественно, что в ущерб производительности и памяти), описав класс работающий с числами независимо от их разрядности (типа BigNum и иже с ним). При грамотном подходе можно реализовать это с довольно небольшими требованиями к памяти и высоким быстродействием (Эх, жаль что на это времени не осталось ).
Re[27]: Ещё раз о галвном :)
От: dr.Chaos Россия Украшения HandMade
Дата: 14.12.06 16:14
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, dr.Chaos, Вы писали:


DC>>Портируемость С++ ты видимо не верно понимаешь . Она говорит о том что стандартная библиотека будет работать на разных платформах одинаково, а то что ты написал, это уж извини как написал так и работает .


E>Ну я понимаю просто. Вот написал я прогу для Win, а кастомеры говорят: "Хотим и под Mac OS!"

E>Вопрос: "сколько будет стоить перенос"
E>Короче в практическо-управленческом ключе
Это в сторону JVM и CLR.

DC>>Использование беззнаковых делает человека более внимательным, а это уже плюс.

E>Ну в принципе так можно поступать всегда, тогда будешь аскетом.
E>Например можно ездить не на удобной иномарке а на очень старой "копейке". Тоже не будет давать слишком сильно лихачить

Ну лихачь, лихачь .
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Re[11]: У всех свои цели :)
От: johny5 Новая Зеландия
Дата: 15.12.06 08:58
Оценка:
Здравствуйте, Erop, Вы писали:

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


J>> Конечно если на 16 битной машине нет 32х битных чисел вообще, то реализовать такой тип — придётся потрудиться. Главная цель — портируемость.


E>А вот если чтобы работала и при этом хорошо (без тормозов, перерасхода ресурсов, органично для целевой платформы и надежно), то все эти ужимки тебе не помогут


Ну в общем ужимки портирования никак не связаны с основным топиком, тут хоть int хоть unsigned, всё равно придётся думать.
При заведомо непродуманном для портирования коде замены unsigned -> int это как случайно поворачивая собирать кубик-рубик в надежде что всё заработает.


E>

J>>Моё ИМХО: выбор signed/unsigned типа — решение проектировщика — это, я понимаю, высокий (абстрактный) уровень. Тут не учитываются детали имплементации а только декларируется соглашение API о принимаемых/возвращаемых значениях. В данном случае вы предоставляете "барьер", человек, предоставляющий unsigned значение должен удостовериться что он предоставляет его правильно, соответственно API может быть спокойна за знаковость значения и наоборот.

E>Вот если бы ещё правила С++ это всё позволяли...

А почему они не позволяют этого? Декларируете что то как unsigned — всё, больше ничего не надо. А поиск ошибок переполнения, ошибок со знаками это задача программиста и компилятора.

E>Ещё раз спрошу: "от чего бы такие ограничения не наложть прямо
Автор: Erop
Дата: 17.11.06
?" Зачем химичить с модульной арифметикой?


Вы там предлагаете вариант int_for_unsigned, что примерно означает: "тут вообще то должен быть unsigned, но т.к. у нас программисты совсем тупые, то мы сделаем int чтобы уменьшить количество ошибок хотя бы с антипереполнением".

Используя только тип int вы понижаете декларативное свойство интерфейсов. Кроме как в комментарии к коду у вас не будет возможности сказать, что значение всегда должно быть положительным. В вашем примере:

int get_buratino_apples(Buratino& )


неочевидно, что функция не может вернуть например -1 как сигнал ошибки, и пользователь будет вынужден явно позаботиться, написав проверку (assert или if). Если он не позаботиться сразу, то позднее, имплементор функции get_buratino_apples может догадаться, что не для всяких буратин функция может вернуть правильное значение и тогда пользователи этой функции "огребут по полной".

прототип функции

unsigned get_buratino_apples(Buratino& )


гарантирует положительность ответа, и если все возвращаемые значения потенциально возможны (т.е. у вас нет способа через возвращаемое значение заявить об ошибке), то проверка на валидность объекта класса Buratino будет уже стоять внутри функции get_buratino_apples.
Re[12]: Пример кода с "преимуществами"
От: Erop Россия  
Дата: 16.12.06 09:41
Оценка:
Здравствуйте, johny5, Вы писали:

J>Ну в общем ужимки портирования никак не связаны с основным топиком, тут хоть int хоть unsigned, всё равно придётся думать.

J>При заведомо непродуманном для портирования коде замены unsigned -> int это как случайно поворачивая собирать кубик-рубик в надежде что всё заработает.
+1. Я про то же. signed/unsigned мало помогает в реальной портируемости кода. Да и вообще в C++ сильно не самый портируемый язык, ИМХО.
E>>

E>>Вот если бы ещё правила С++ это всё позволяли...
J>А почему они не позволяют этого? Декларируете что то как unsigned — всё, больше ничего не надо. А поиск ошибок переполнения, ошибок со знаками это задача программиста и компилятора.
Ну, например, потому, что так устроены правила выбора результата целочисленной операции.
Смотри, пусть i -- это int si -- signed int, а ui -- это unsigned int (так же и s, ss и us).
Каковы, по товоему, типы (и результаты) следующих результатов вычислений?
    unsigned int ui = 2;
    int i = 2;
    signed int si = -2;

    signed short ss = -2;
    short s = 2;
    unsigned short us = 2;
    
    ui - ui;    // это мне "нравится". 
    ui + ui;
    ui * si;    // это мне "нравится". 
        us + us;
    ui * ss;    // сопоставление этого и следующего мне тоже очень "нравится"
    us * ss;  
    ui % ss;    // тоже весьма "логично"  :shuffle:
Ну и так далее...

Вот скажем тебе надо закодировать какую-то формулу, скажем такую простую:
max( xxxQuality / 2 + yyyUnsignedQuality * yyyCoef, zzzQuality + zzzQualityShift );
Вот если, скажем тут yyyUnsignedQuality не может быть отричательным чисорм и по этому оно unsigned, то результат этого выражения начинает сильно очень зависеть от типов всех параметров
Ну вот и на хрена ерундой заниматься? Может лучше отлаживать таки саму формулу, а не особенности её кодироания с использованием unsigned типов?


J>Вы там предлагаете вариант int_for_unsigned, что примерно означает: "тут вообще то должен быть unsigned, но т.к. у нас программисты совсем тупые, то мы сделаем int чтобы уменьшить количество ошибок хотя бы с антипереполнением".
Не, это обозначает, ровно то, что написано: "Челое число, которое, если не отходить очень далеко от 0, ведёт себя как число, которому запрещено принимать отрицательные значения). При чём тут вообще арифметика по модулю 2 в какой-то степени (AKA тип unsigned int)?

J>Используя только тип int вы понижаете декларативное свойство интерфейсов. Кроме как в комментарии к коду у вас не будет возможности сказать, что значение всегда должно быть положительным. В вашем примере:


J>
J>int get_buratino_apples(Buratino& )
J>


J>неочевидно, что функция не может вернуть например -1 как сигнал ошибки, и пользователь будет вынужден явно позаботиться, написав проверку (assert или if). Если он не позаботиться сразу, то позднее, имплементор функции get_buratino_apples может догадаться, что не для всяких буратин функция может вернуть правильное значение и тогда пользователи этой функции "огребут по полной".


Как интересно! А что же будет, если функция будет возвращать unsigned, а "имплементор функции get_buratino_apples может догадаться, что не для всяких буратин функция может вернуть правильное значение"?
Если будут возвращать UINT_MAX, а вызывающая сторона не ухом ни рылом, то конечно будет намного лучше.
Ещё можешь обдумать такую вот тему. Предтавь, что результат как-то так используют, что существенно закладываются на неотрицательность. Скажем аллокирут массив, под хранение свойств каждого из яблок. Если тип, возвращают signed, то случится что?
Если напишут assert, то он провалится и мы сразу всё отладим, а если, например, нет assert, то случится какая-то хитрая ошибка в new, и тоде будут таки шансы всё отладить.
А вот если какой-то урод, стёр в интрефесе комментарий, поменял семантику метода, не поменяв его имени, и начал таки возвращать вместо числа яблок число UINT_MAX, то принимающий код скорее всего не будет содержать никакого вменяемого assert'а. Кроме того, new просто и незамысловато сможет ответить "не хватает памяти".

Ну вот и у тебя прекрасная ситуация. Работает твоя прога. В каком-то редком случае на большом запросе случается нехватка памяти. Твои действия?
(Альтернатива -- assert => сразу ясно что случилось)

J>прототип функции

J>
J>unsigned get_buratino_apples(Buratino& )
J>


J>гарантирует положительность ответа, и если все возвращаемые значения потенциально возможны (т.е. у вас нет способа через возвращаемое значение заявить об ошибке), то проверка на валидность объекта класса Buratino будет уже стоять внутри функции get_buratino_apples.


А вот и фигушки! Тот "мегаразработчик", который начнёт неожиданно из функции "число яблок", в комментарии которой написано, что типа результат -- 0 или больше, возвращать значение "-5" может и тип результата поменять вообще-то.

А что мешает так же делать и с signed ответом?
Опять же, что мешает, (если реально возникают такие проблемы), использовать int_for_unsigned
Автор: Erop
Дата: 17.11.06
?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[14]: Беззнаковые иллюзии
От: Erop Россия  
Дата: 16.12.06 09:47
Оценка:
Здравствуйте, johny5, Вы писали:


J>Хорошо, но вы согласны, что unsigned даёт просто больше декларативной информации чем int (целое и положительное vs целое)?

Я согласен, что слово unsignrd, написанное перд функцией можно договориться считать обозначающим именно это -- 2функция возвращает вообще-то числа, но неотрицательные", но это намного дороже, чем договориться писать про это в комментариях.
Почему? -- Да потому, что слово unsigned говорит языку C++ много такого, чего лучше бы не говорить

Могу привести пример (я его, кажется уже приводил, но не нашёл где)
Можно, примерно так же, договориться, что слово register маркирует переменные, которые связаны с регистрацией чего-нибудь в госрганах, а слово auto -- омееющие отношение к автомобилям.
В принципе можно, но есть две проблемы
1) Во всех других случаях мы так не делаем. То есть про автомобили, чётные числа, ограниченность результата сверху мы пишем в комментариях или в названиях идентифекаторов, а не при помощи подходящих по звучанию ключевых слов C++
2) Эти все ключевые слова как-то меняют код. Далеко не всегда удачно.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Нужен ли unsigned
От: Programador  
Дата: 11.04.07 11:51
Оценка:
Здравствуйте, Андрей Тарасевич,

Вы писали:

АТ>Результат знакового целочисленного переполнения — UB. Беззнаковые типы реализуют арифметику по модулю, т.е. у них не бывает "переполнения" или, другими словами, традиционное переполнение у них приводит к однозначно оговоренному эффекту без какого-либо UB.


ТОлько этот модуль не оговорен В документе исо 14882-1998 — 3ю9ю1ю4 (не могу закопипастить) сказано про particular size of integer. С предыдущим пунктом это можно трактовать как 2^31 причем сомнительно можно ли particular трактовать как модуль 2^32 Помоему совпадение это не particular Другими словами может ли диапазон быть больше самого большого знакового Ну или не UB, но во всех компиляторах не так
Re[21]: Давай немного подробнее?
От: CreatorCray  
Дата: 16.04.07 00:32
Оценка:
Здравствуйте, Erop, Вы писали:

E>>1. Не вижу смысла использоваться знаковые целые для величин, которые не будут отрицательными -> дополнительная информация тому, кто будет использовать код

E>Это вообще не выгода Выгода, это когда ты что-то получаешь.
E>Видимо то, что слово unsigned в С++ обозначает нечто очень своеобразное и совсем другое (модульная арифметика, тоо сё) тебе не важно.
Ну, не знаю чем вам так не угодили беззнаковые типы. Мне как начинавшему с ассемблера что int что unsigned int — один фиг. Только в умножении/делении разница. И беззнаковое для меня применительно к значениям, которые не могут стать отрицательными гораздо логичнее чем гипотетическая выгода в вылете в отрицательную область значений при каком либо выверте кода. Я не могу вспомнить когда последний раз сталкивался с подобной проблемой.

E>>2. Т.к. нет отрицательных значений убирается проверка на то, что значение выскочило "ниже" положенного. То, что удобно ловить ошибки по отрицательным — не соглашусь, ошибку нужно ловить перед выполнением операции.

E>А в чём смысл? Идея в том, что так эффективнее или в чём-то ещё?
Разумеется эффективнее

E>>3. Если в коде с беззнаковой арифметикой содержится ошибка, то она очень быстро даст о себе знать, в отличие от знаковой, на которой до поры, до времени всё будет работать, а когда ошибка даст о себе знать, то тогда уже может понадобиться ни день, и не два на отладку. Вполне возможно, что всё будет работать до самого релиза.

Абсолютно согласен.

E>Просто во втором проще ошибиться

Ну пардон, принцип "сперва подумай — потом сделай" никто не отменял.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[23]: Давай немного подробнее?
От: CreatorCray  
Дата: 16.04.07 00:32
Оценка:
Здравствуйте, Erop, Вы писали:

E>1) Твой код не эквивалентен моему

E>У меня массив итерируется с конца в начало! А вдруг мне надо именно так?
E>Вот при знаковом i всё равно куда и с каким шагом итерировать, а вот с unsigned начинаются косяки и двери
Не вопрос:

unsigned int i = count;
while (i--)
   do_somthing (i);


Коротко и просто. Будет работать как для int так и для uint. В чем проблема то? Что то мне все больше кажется что в личной неприязни к unsigned.
"Как? Ви не любите кошекЪ??? Та ви просто не умеете их готовить!!!" (С)
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: Всё очень просто....
От: CreatorCray  
Дата: 16.04.07 00:32
Оценка:
Здравствуйте, <Аноним>, Вы писали:

Ш>>Например, напиши struct IPHeader без беззнаковых типов. Или сделай алгоритм вычисления CRC (а так же SHA, DES, длинная арифметика и.т.п.).

А>То есть ты прибавляешь один IP к другому, а порты отнимаешь друг от друга и две получившиеся величины перемножаешь между собой?

Сам то понял что сказал?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: Нужен ли unsigned
От: CreatorCray  
Дата: 16.04.07 00:32
Оценка:
Здравствуйте, Шахтер, Вы писали:

R>>Я думаю таких примеров можно найти ещё.

Ш>Примеров откровенного ламерства, когда люди простейший цикл не могут написать, действительно можно найти вагон и прицепную тележку.
+100!

Ш>Точно так же нет вещественных, и всё что мы имеем -- это жалкий float.

Ну и чуть чуть менее жалкий double
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[15]: Спрашиваю исключительно из интереса
От: CreatorCray  
Дата: 16.04.07 00:32
Оценка:
Здравствуйте, Erop, Вы писали:

E>Я пользуюсь библиотекой, которую ты скорее всего не знаешь. Она чем-то похожа на MFC в области коллекций. Sort там реализован, а остальное вроде как бывает нужно крайне редко.

Название у библиотеки имеются? URL?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[15]: unsigned
От: CreatorCray  
Дата: 16.04.07 00:32
Оценка:
Здравствуйте, Пётр Седов, Вы писали:

E>>И ещё меня, допустим, удивляет реализация CArray, где метод GetSize() возвращает int.

ПС>Это перестанет удивлять после дня, потраченного на поиск ошибки из-за беззнаковой арифметики.
Нахождение подобной ошибки ИМХО означает что "тут писали не подумав". Да и к слову находится она очень быстро по причине получающихся огромных значений которые мало того, что означают переполнение так и отслеживаются на ура.

ПС>За что? За то, что направляет новичков на грабли (беззнаковая арифметика)?

"И опыт, сын ошибок трудных"
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[15]: Закон перехода количества в качество.
От: CreatorCray  
Дата: 16.04.07 00:32
Оценка:
Здравствуйте, Erop, Вы писали:

E>Что-то мне подсказывает, что он таки столкнулся с переполнением, при попытке взыскать долг

Ага. И выдал мудрецу -1 зерно
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Решите тогда задачу
От: CreatorCray  
Дата: 16.04.07 00:32
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Как эту задачу решить правильно, я затрудняюсь сказать. В псевдокоде она решается одной строчкой:

RO>unsigned f(unsigned n, int s)
RO>{
RO> return s % n;
RO>}

Не вникал в задачу
ответ "наугад", можно сказать по интуиции

unsigned f(unsigned n, int s)
{
  return (s+n) % n;
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[12]: А ради чего таки все эти усилия? :)
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 16.04.07 03:10
Оценка:
Здравствуйте, Erop, Вы писали:

E>И что? На каждый результат каждого действия писать другой тип?

E>Это же дополнительная работа программиста. Дополгнительное время.

ты не поверишь, но люди еще и стараются чтоб у них килограммы с метрами не складывались — Обеспечение семантического контроля над размерностями
Автор: CrystaX
Дата: 21.11.05
... << RSDN@Home 1.2.0 alpha rev. 675>>
Re[7]: offtopic
От: Erop Россия  
Дата: 19.04.07 10:34
Оценка:
Здравствуйте, Ulfur, Вы писали:

U>В конечном счете именно С++ (на С мой подход по естественным причинам не повторить) позволил избежать ряда грубых ошибок и падений — ценой производительности, но только в отладочной сборке.


В целом я бы при таком переносе действовал так:

1) Мспользовал бы всюду вместо int мой тип, который в разных версиях программы можно превратить в long, int или специальный тип, типа int с контролем корректности.

2) Запустил бы какую-то тестовую выборку запросов и подобрал бы параметры так, чтобы запрос был типовым, а переполнений не было (места, где переполнения на типовом запросе неизбежны, по любому надо сделать long )

3) Откомпилил бы версию, в котрой int'ы остались int'ами и попрофилировал бы её на том самом "типовом, но беспроблемном" запросе.

4) Потмо откомпилил бы так, чтобы int'ы были long и тоже попрофилировал бы.

5) Сравнивая профили из 3 и из 4 переписал бы руками критичные места, производительность котоорых пострадала (это не только из-а int-long может бытьно и из-за многих других причин)


Правда на этом пути будет ещё трудность связанная с совместимостью сохраняемых данных и другими способами заложиться на оразмеры типов. Ну и всякие хаккерские приёмы конечно тоже будут мешать. Но если код не слишком извратный, то эти все места должны легко искаться.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Нужен ли unsigned
От: 0x8000FFFF Россия  
Дата: 19.04.07 11:55
Оценка:
Могу посоветовать только учить С... дабы понимать что к чему и зачем.
Re[15]: Беззнаковые иллюзии
От: Sinclair Россия https://github.com/evilguest/
Дата: 26.04.07 11:58
Оценка:
Здравствуйте, Пётр Седов, Вы писали:

ПС>Здравствуйте, johny5, Вы писали:

J>>Хорошо, но вы согласны, что unsigned даёт просто больше декларативной информации чем int (целое и положительное vs целое)?
ПС>Да. Но, во-первых, эта декларативность не подкрепляется run-time-проверками (в широко используемых компиляторах).
ПС>Во-вторых, арифметика с unsigned int беззнаковая. В простых случаях (например, итерация массива в прямом порядке) беззнаковая арифметика не вызывает проблем. Но когда появляется беззнаковое вычитание, риск ошибиться возрастает (так как беззнаковая арифметика отличается от обычной в районе нуля). Беззнаковая арифметика — низкоуровневая техника. Она позволяет выжать из компьютера максимум (дополнительный бит), но за это приходится платить. Код с беззнаковой арифметикой хрупкий, подвержен ошибкам. От программиста требуется повышенное внимание/напряжение, иначе любое изменение кода может незаметно внести ошибку (которая проявляется только в граничном случае; например, когда vec.size() = 0). А вот код со знаковой арифметикой часто не содержит ошибок просто потому, что вычисляется именно то, что имел в виду программист.
Нет. Код со знаковой арифметикой как правило содержит ошибки, просто они редко проявляются. Я уже приводил пример вычисления среднего значения. Вот он:
int aver(int a, int b)
{
  return (a + b) / 2;
}


Он, конечно же, вычисляет именно то, что имел в виду программист. Но не всегда. Давайте посчитаем среднее от, к примеру, (2000000000 и 2000000000), а? Каждое число является вполне нормальным знаковым 32-х разрядным целым. Результат тоже. Но программист, наверное, имел в виду получить всё же 2000000000, а не -147483648, не так ли?

В итоге, корректность кода обеспечивается, грубо говоря, тем, что в реальной жизни до двух миллиардов ни a ни b не дорастают. Ну или дорастают, где-то вылезает бяка, и в следующей версии продукта ее успешно чинят.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[16]: Фиксированная vs. динамическая арифметика
От: Пётр Седов Россия  
Дата: 26.04.07 15:28
Оценка:
Здравствуйте, Sinclair, Вы писали:

ПС>>А вот код со знаковой арифметикой часто не содержит ошибок просто потому, что вычисляется именно то, что имел в виду программист.

S>Нет. Код со знаковой арифметикой как правило содержит ошибки, просто они редко проявляются. Я уже приводил пример вычисления среднего значения. Вот он:
S>
S>int aver(int a, int b)
S>{
S>  return (a + b) / 2;
S>}
S>


S>Он, конечно же, вычисляет именно то, что имел в виду программист. Но не всегда. Давайте посчитаем среднее от, к примеру, (2000000000 и 2000000000), а? Каждое число является вполне нормальным знаковым 32-х разрядным целым. Результат тоже. Но программист, наверное, имел в виду получить всё же 2000000000, а не -147483648, не так ли?

Такой пример можно придумать для любого арифметического типа фиксированного размера (например, 32 бита), в том числе для unsigned int. Поэтому Ваш пример не относится к спору «знаковая арифметика vs. беззнаковая арифметика». Ваш пример относится к спору «фиксированная арифметика vs. динамическая арифметика».
Кстати, насколько я знаю, в языке Ruby целочисленная арифметика – динамическая.

S>В итоге, корректность кода обеспечивается, грубо говоря, тем, что в реальной жизни до двух миллиардов ни a ни b не дорастают. Ну или дорастают, где-то вылезает бяка, и в следующей версии продукта ее успешно чинят.

Да, но этому подвержена любая фиксированная арифметика – знаковая или беззнаковая.
Пётр Седов (ушёл с RSDN)
Re[17]: Фиксированная vs. динамическая арифметика
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.04.07 02:00
Оценка:
Здравствуйте, Пётр Седов, Вы писали:

ПС>Здравствуйте, Sinclair, Вы писали:


ПС>>>А вот код со знаковой арифметикой часто не содержит ошибок просто потому, что вычисляется именно то, что имел в виду программист.

S>>Нет. Код со знаковой арифметикой как правило содержит ошибки, просто они редко проявляются. Я уже приводил пример вычисления среднего значения. Вот он:
S>>
S>>int aver(int a, int b)
S>>{
S>>  return (a + b) / 2;
S>>}
S>>


S>>Он, конечно же, вычисляет именно то, что имел в виду программист. Но не всегда. Давайте посчитаем среднее от, к примеру, (2000000000 и 2000000000), а? Каждое число является вполне нормальным знаковым 32-х разрядным целым. Результат тоже. Но программист, наверное, имел в виду получить всё же 2000000000, а не -147483648, не так ли?

ПС>Такой пример можно придумать для любого арифметического типа фиксированного размера (например, 32 бита), в том числе для unsigned int. Поэтому Ваш пример не относится к спору «знаковая арифметика vs. беззнаковая арифметика». Ваш пример относится к спору «фиксированная арифметика vs. динамическая арифметика».
Мой пример относится к утверждению "вот код со знаковой арифметикой часто не содержит ошибок".

ПС>Да, но этому подвержена любая фиксированная арифметика – знаковая или беззнаковая.

Совершенно верно.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[19]: Большие числа
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.04.07 02:58
Оценка:
Здравствуйте, Пётр Седов, Вы писали:
S>>Мой пример относится к утверждению "вот код со знаковой арифметикой часто не содержит ошибок".
ПС>По моим понятиям, функция aver не содержит ошибок.
А можно пояснить эти понятия? По моим понятиям, aver(x, x) == x должно быть true для любого x.
Функция aver в данном варианте содержит малоприятный баг, который тем более опасен, что проявляется не всегда.

ПС> А числа порядка миллиарда – это большая экзотика. 32-битного int-а хватает почти всегда с хорошим запасом.

Для чего хватает?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[20]: Большие числа
От: aka50 Россия  
Дата: 27.04.07 06:56
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Пётр Седов, Вы писали:

S>>>Мой пример относится к утверждению "вот код со знаковой арифметикой часто не содержит ошибок".
ПС>>По моим понятиям, функция aver не содержит ошибок.
S>А можно пояснить эти понятия? По моим понятиям, aver(x, x) == x должно быть true для любого x.
S>Функция aver в данном варианте содержит малоприятный баг, который тем более опасен, что проявляется не всегда.
Дело в том, что для знаковой арифметике проблема может быть решена, т.к. нужно контролировать только переполнение:
int aver(int a, int b)
{
  return (a & b) + ((a ^ b) >> 1);
}


А вот в signed/unsigned проблемы удваиваются, т.к. помимо signed проблем еще и проблема смешивания добавляется.
double Foo(unsigned int X,unsigned int Y, double D)
{
    return (X-Y)*D;
}


Хотя я лично считаю, что Sun зря не ввел unsigned хотя бы как несовместимый с signed тип, реализация низкоуровневых вещей получается ну очень многословной и с кучей грабель.
Re[21]: Большие числа
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.04.07 07:38
Оценка:
Здравствуйте, aka50, Вы писали:
A>Дело в том, что для знаковой арифметике проблема может быть решена, т.к. нужно контролировать только переполнение:
A>
A>int aver(int a, int b)
A>{
A>  return (a & b) + ((a ^ b) >> 1);
A>}
A>

Дело совершенно не в этом. Дело как раз в том, что вот такой простейший код делает совершенно не то, чего ожидал программист.
Починить его относительно нетрудно; но это нужно делать руками.

A>А вот в signed/unsigned проблемы удваиваются, т.к. помимо signed проблем еще и проблема смешивания добавляется.

Никакого удвоения не происходит. Это та же самая проблема выхода за диапазон. Просто диапазон другой.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[22]: Большие числа
От: aka50 Россия  
Дата: 27.04.07 09:28
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


A>>А вот в signed/unsigned проблемы удваиваются, т.к. помимо signed проблем еще и проблема смешивания добавляется.

S>Никакого удвоения не происходит. Это та же самая проблема выхода за диапазон. Просто диапазон другой.
Я имел ввиду неоднозначность преобразования. Что будет умножаться на signed double. unsigned int или signed int.
Re[23]: Беззнаковое вычитание
От: Пётр Седов Россия  
Дата: 27.04.07 21:59
Оценка:
Здравствуйте, aka50, Вы писали:
A>Я имел ввиду неоднозначность преобразования. Что будет умножаться на signed double. unsigned int или signed int.
Всё однозначно: разность двух unsigned int – тоже unsigned int. Это называется «беззнаковое вычитание».
(Речь идёт о C/C++.)
Пётр Седов (ушёл с RSDN)
Re[20]: Понятия
От: Пётр Седов Россия  
Дата: 27.04.07 23:06
Оценка:
Здравствуйте, Sinclair, Вы писали:

ПС>>По моим понятиям, функция aver не содержит ошибок.

S>А можно пояснить эти понятия?
Если int – 32-битный, то его ограниченностью можно пренебречь (в большинстве случаев).

S>По моим понятиям, aver(x, x) == x должно быть true для любого x.

За такую строгость придётся дорого платить.

S>Функция aver в данном варианте содержит малоприятный баг, который тем более опасен, что проявляется не всегда.

Bug – это скорее свойство не функции, а программы. Например, функция aver может использоваться только для чисел 0 .. 100. Это можно выразить явно:
int aver(int a, int b)
{
  assert((0 <= a) && (a <= 100));
  assert((0 <= b) && (b <= 100));
  return (a + b) / 2;
}

Тогда ошибки нет даже по Вашим понятиям.

ПС>> А числа порядка миллиарда – это большая экзотика. 32-битного int-а хватает почти всегда с хорошим запасом.

S>Для чего хватает?
Для работы с целыми числами.
Пётр Седов (ушёл с RSDN)
Re[21]: Понятия
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.04.07 02:55
Оценка:
Здравствуйте, Пётр Седов, Вы писали:
ПС>За такую строгость придётся дорого платить.
С чего вы взяли, что за нестрогость придется платить дешевле?
S>>Функция aver в данном варианте содержит малоприятный баг, который тем более опасен, что проявляется не всегда.
ПС>Bug – это скорее свойство не функции, а программы.
Конечно же да! Но полагаться на "авось" — не лучший способ обеспечивать безошибочность программы.
ПС>Например, функция aver может использоваться только для чисел 0 .. 100. Это можно выразить явно:
Это нужно выражать явно. Иначе рано или поздно ракета упадет, а начисленная зарплата окажется отрицательной.
ПС>
ПС>int aver(int a, int b)
ПС>{
ПС>  assert((0 <= a) && (a <= 100));
ПС>  assert((0 <= b) && (b <= 100));
ПС>  return (a + b) / 2;
ПС>}
ПС>

ПС>Тогда ошибки нет даже по Вашим понятиям.
Совершенно верно. Но это — совсем другой код.
ПС>Для работы с целыми числами.
Ок. Если придете к нам на собеседование, не забудьте упомянуть об этой дискуссии.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[24]: Давай немного подробнее?
От: Erop Россия  
Дата: 01.05.07 15:35
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>
CC>unsigned int i = count;
CC>while (i--)
CC>   do_somthing (i);
CC>


CC>Коротко и просто. Будет работать как для int так и для uint. В чем проблема то? Что то мне все больше кажется что в личной неприязни к unsigned.

Мало того, что это несколько нечитабельно, так ты ещё и невнимательно прочитал что хочется. Хочется итерировать с щагом...

скажем с шагом step...

CC>"Как? Ви не любите кошекЪ??? Та ви просто не умеете их готовить!!!" (С)
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[16]: Спрашиваю исключительно из интереса
От: Erop Россия  
Дата: 01.05.07 15:39
Оценка:
Здравствуйте, CreatorCray, Вы писали:

E>>Я пользуюсь библиотекой, которую ты скорее всего не знаешь. Она чем-то похожа на MFC в области коллекций. Sort там реализован, а остальное вроде как бывает нужно крайне редко.

CC>Название у библиотеки имеются? URL?

Устроишься работать к нам -- узнаешь
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[25]: Давай немного подробнее?
От: CreatorCray  
Дата: 03.05.07 05:54
Оценка:
Здравствуйте, Erop, Вы писали:

E>Мало того, что это несколько нечитабельно

Да ну???

E> так ты ещё и невнимательно прочитал что хочется. Хочется итерировать с щагом...

У тебя там код без шага. Тебе привели код эквивалентный твоему по логике. Шага у тя не было.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[26]: Давай немного подробнее?
От: Erop Россия  
Дата: 06.05.07 19:34
Оценка:
Здравствуйте, CreatorCray, Вы писали:

E>> так ты ещё и невнимательно прочитал что хочется. Хочется итерировать с щагом...

CC>У тебя там код без шага. Тебе привели код эквивалентный твоему по логике. Шага у тя не было.
очень хорошо. А если таки надо с шагом?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Нужен ли unsigned
От: Eugeny__ Украина  
Дата: 23.05.07 14:44
Оценка:
Здравствуйте, Аноним, Вы писали:

Когда нужно писать побитовые операции, перемежая их с обычными арифметическими (например, пересчет crc), signed типы есть немалое зло. В java нет signed типов, а про знаковый бит я как-то сразу не подумал, когда писал на java драйвер для девайса. Долго матюкался, переводя все на беззнаковый char(при это еще и char более расточителен: в java он занимает 2 байта, один из которых никогда не использовался, так как все операции были с байтами).
Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.
Re[2]: Нужен ли unsigned
От: Пётр Седов Россия  
Дата: 23.05.07 20:43
Оценка:
Здравствуйте, Eugeny__, Вы писали:

E__>Когда нужно писать побитовые операции, перемежая их с обычными арифметическими (например, пересчет crc), signed типы есть немалое зло.

Как раз для таких задач unsigned int и беззнаковая арифметика подходят хорошо. Но такие задачи – экзотика, а не повседневная жизнь.

E__>В java нет signed типов,

Чего?

E__>а про знаковый бит я как-то сразу не подумал, когда писал на java драйвер для девайса.

На Java писать драйвер?!

E__>Долго матюкался, переводя все на беззнаковый char(при это еще и char более расточителен: в java он занимает 2 байта, один из которых никогда не использовался, так как все операции были с байтами).

Может, Java Glossary поможет:

To get the effect of an 8-bit unsigned:

byte b;
// ...
int i = b & 0xff;

To get the effect of effect of a 16-bit unsigned use char.
To get the effect of a 32-bit unsigned:
int i;
// ...
long l = i & 0xffffffffL;


Изначально это обсуждение было в форуме «C/C++», поэтому просьба не приплетать Java и прочих.
Пётр Седов (ушёл с RSDN)
Re[3]: Нужен ли unsigned
От: Eugeny__ Украина  
Дата: 24.05.07 08:33
Оценка:
Здравствуйте, Пётр Седов, Вы писали:

ПС>Здравствуйте, Eugeny__, Вы писали:


E__>>Когда нужно писать побитовые операции, перемежая их с обычными арифметическими (например, пересчет crc), signed типы есть немалое зло.

ПС>Как раз для таких задач unsigned int и беззнаковая арифметика подходят хорошо. Но такие задачи – экзотика, а не повседневная жизнь.
Даа, особенно на java

E__>>В java нет signed типов,

ПС> Чего?
Запарился. Нет unsigned числовых, кроме short, но short не подходит по другой причине.

E__>>а про знаковый бит я как-то сразу не подумал, когда писал на java драйвер для девайса.

ПС>На Java писать драйвер?!
С матюками, зато не скучно
Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.