Даже во многих современных программах на C++ часто вижу int/short/long там, где по смыслу должно быть беззнаковое целое. А в ранних программах знаковые целые вообще использовались везде, где было технически возможно. Даже в классической книге Кернигана/Ритчи множество примеров, где счетчики, индексы и прочие имеют знаковый тип. В виндовых SDK, где знаковость в основном используется адекватно, все равно регулярно встречаются знаковые параметры размеров, количеств и прочего, где не используются отрицательные значения для особых случаев.
Откуда такое пристрастие, кроме как от лени? Вроде как сколько-нибудь массовых процессоров, где беззнаковые целые поддерживались бы ограниченно, не существует. Есть в этом хоть какое-то рациональное зерно?
09.05.20 12:07: Перенесено из 'Компьютерные священные войны'
10.05.20 22:31: Перенесено из 'Компьютерные священные войны'
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Даже во многих современных программах на C++ часто вижу int/short/long там, где по смыслу должно быть беззнаковое целое.
Писать зело больше
ЕМ>А в ранних программах знаковые целые вообще использовались везде, где было технически возможно. Даже в классической книге Кернигана/Ритчи множество примеров, где счетчики, индексы и прочие имеют знаковый тип. В виндовых SDK, где знаковость в основном используется адекватно, все равно регулярно встречаются знаковые параметры размеров, количеств и прочего, где не используются отрицательные значения для особых случаев.
Про отрицательные значения и то, что они не используются — ты не можешь быть уверен. Но таки да, может и по лени или недосмотру.
ЕМ>Откуда такое пристрастие, кроме как от лени? Вроде как сколько-нибудь массовых процессоров, где беззнаковые целые поддерживались бы ограниченно, не существует. Есть в этом хоть какое-то рациональное зерно?
Нет.
От тебя много батхерта последнее время. Тебя из РФ не выпускают, как я понимаю?
Знаковые целые тупо безопаснее. Беззнаковость в STL — это огромная историческая ошибка, даже Степанов это признал.
Ты на беззнаках даже тупо от ЭН до нуля проитерироваться не можешь без дополнительного бубна.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, Marty, Вы писали:
M>Писать зело больше
О да, uint вместо int, ulong вместо long — это ж пальцы отобьешь...
M>Про отрицательные значения и то, что они не используются — ты не можешь быть уверен.
Что значит "не могу"? Если я по коду вижу, что особые случаи не предусмотрены — что еще нужно для уверенности? А если количество чего-то, по логике не превышающего, скажем, 1000, в результате ошибки окажется -10, то чем это может быть лучше 50000?
M>От тебя много батхерта последнее время.
Не больше, чем обычно. Так-то у меня сейчас дела идут сильно лучше, чем зимой, так что не в этом дело.
M>Тебя из РФ не выпускают, как я понимаю?
Сейчас уже вроде выпускают, но пока сообщение толком не наладилось. К середине месяца, надеюсь, что-то двинется.
Здравствуйте, T4r4sB, Вы писали:
TB>Знаковые целые тупо безопаснее.
В отдельных случаях — согласен. Но никак не в общем.
TB>Беззнаковость в STL — это огромная историческая ошибка, даже Степанов это признал.
В чем именно? Я не слежу за развитием STL.
TB>Ты на беззнаках даже тупо от ЭН до нуля проитерироваться не можешь без дополнительного бубна.
А насколько часто нужно повторять от N до нуля включительно? По-моему, это весьма частный случай, встречается очень редко. Какие есть типовые случаи?
Лично я с самого начала своей практики на C/C++ (начало 90-х) использую для счетчиков, количеств, размеров и прочего только беззнаковые. Случаев, подобных упомянутому, или неочевидных ошибок за это время были единицы. А вот проблем и глюков из-за бессмысленных преобразований туда-сюда, по причине знаковости функций CRT и API — сотни. Что я все это время делал не так?
Здравствуйте, Евгений Музыченко, Вы писали:
M>>Писать зело больше
ЕМ>О да, uint вместо int, ulong вместо long — это ж пальцы отобьешь...
Таких типов нет, если что
M>>Про отрицательные значения и то, что они не используются — ты не можешь быть уверен.
ЕМ>Что значит "не могу"? Если я по коду вижу, что особые случаи не предусмотрены — что еще нужно для уверенности? А если количество чего-то, по логике не превышающего, скажем, 1000, в результате ошибки окажется -10, то чем это может быть лучше 50000?
Может унутре используются. То, что к тебе отрицательные значения не попадают, это еще ничего не значит
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Откуда такое пристрастие, кроме как от лени? Вроде как сколько-нибудь массовых процессоров, где беззнаковые целые поддерживались бы ограниченно, не существует. Есть в этом хоть какое-то рациональное зерно?
Что сразу вспомнилось:
1. Про итерирование от N до 0 уже написали, но повторюсь.
2. OpenMP. Неожиданно, но Майкрософт в своём компиляторе поддерживает только очень старую версию 2.0, в ней индексы для for могут быть только знаковыми.
3. Адресная арифметика вся знаковая, родной тип ptrdiff_t. То есть если я захочу сделать размеры картинки (ширину и высоту) сделать, например, size_t и ходить по изображению по байтам, то мне всё равно надо переходить к ptrdiff_t, чтобы компилятор не ругался.
4. Внезапно оказывается, что многие типы становятся знаковыми, хотя по логике они такими быть, на первый взгляд, не могут. Например, детектирую я пешеходов и авто на кадре. И их левая координата уходит в минус, если в кадре видна только часть автомобиля.
5. Далее знаковые становятся удобнее, когда происходит преобразование в другие системы координат. В твоей экранной системе координаты только положительные, ты рисуешь график в декартовой и числа внезапно становятся отрицательными.
6. Даже яркость пикселя, которая чаще всего от 0 до 255 и представлена в uchar при манипуляциях с яркостью легко вылезает за пределы типа вверх и вниз, поэтому тут либо ставить кучу проверок, либо при манипуляциях кастовать в int, а потом обратно. Хотя тут больше есть ограничение на тип, но если сделать его и uint64, легче не станет.
Получается, что большая часть моих кейсов сводится к тому, что естественные ограничения на беззнаковость идут к херам при вычислениях с этими типами. Насколько размер одного контейнера больше второго? Нельзя просто так взять и вычесть! Надо написать if (v1.size() > v2.size())...
Ну куда такое годится?
ЕМ>>Даже во многих современных программах на C++ часто вижу int/short/long там, где по смыслу должно быть беззнаковое целое. M>Писать зело больше
На одну букву — это сильно больше???
ЕМ>>А в ранних программах знаковые целые вообще использовались везде, где было технически возможно. Даже в классической книге Кернигана/Ритчи множество примеров, где счетчики, индексы и прочие имеют знаковый тип. В виндовых SDK, где знаковость в основном используется адекватно, все равно регулярно встречаются знаковые параметры размеров, количеств и прочего, где не используются отрицательные значения для особых случаев.
M>Про о трицательные значения и то, что они не используются — ты не можешь быть уверен. Но таки да, может и по лени или недосмотру.
Особенно, когда отрицательным значением задаются размеры в структурах: мы ведь не можем быть уверены, что переданный буфер не имеет отрицательного размера.
Всё сказанное выше — личное мнение, если не указано обратное.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>А насколько часто нужно повторять от N до нуля включительно? По-моему, это весьма частный случай, встречается очень редко. Какие есть типовые случаи?
От N-1 до нуля включительно — на самом деле хотелось бы весьма часто. Но так как size_t и его производные — беззнаковый, то я стараюсь обходится без такого. Хотя и неудобно бывает
ЕМ>Лично я с самого начала своей практики на C/C++ (начало 90-х) использую для счетчиков, количеств, размеров и прочего только беззнаковые.
Имхо это как раз стандартной библиотекой и привито
ЕМ>Случаев, подобных упомянутому, или неочевидных ошибок за это время были единицы.
Но таки были
ЕМ>А вот проблем и глюков из-за бессмысленных преобразований туда-сюда, по причине знаковости функций CRT и API — сотни. Что я все это время делал не так?
Так наверно преобразования возникали как раз из-за безнаковости плюсовых привычек, а АПИ хотят знаковые
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>А насколько часто нужно повторять от N до нуля включительно? По-моему, это весьма частный случай, встречается очень редко. Какие есть типовые случаи?
От нуля до N-1. На беззнаковых такой перебор записывается довольно неестественно.
Знак это дополнительный маркер, что мы вышли за диапазон в другую сторону.
ЕМ>Лично я с самого начала своей практики на C/C++ (начало 90-х) использую для счетчиков, количеств, размеров и прочего только беззнаковые. Случаев, подобных упомянутому, или неочевидных ошибок за это время были единицы. А вот проблем и глюков из-за бессмысленных преобразований туда-сюда, по причине знаковости функций CRT и API — сотни. Что я все это время делал не так?
А не надо было преобразовывать, надо было всё делать знаковым.
Ссылку на Степанова пока не помню, постараюсь найти.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, Nuzhny, Вы писали:
N>Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>>Откуда такое пристрастие, кроме как от лени? Вроде как сколько-нибудь массовых процессоров, где беззнаковые целые поддерживались бы ограниченно, не существует. Есть в этом хоть какое-то рациональное зерно?
N>Что сразу вспомнилось: N>1. Про итерирование от N до 0 уже написали, но повторюсь. N>2. OpenMP. Неожиданно, но Майкрософт в своём компиляторе поддерживает только очень старую версию 2.0, в ней индексы для for могут быть только знаковыми. N>3. Адресная арифметика вся знаковая, родной тип ptrdiff_t. То есть если я захочу сделать размеры картинки (ширину и высоту) сделать, например, size_t и ходить по изображению по байтам, то мне всё равно надо переходить к ptrdiff_t, чтобы компилятор не ругался. N>4. Внезапно оказывается, что многие типы становятся знаковыми, хотя по логике они такими быть, на первый взгляд, не могут. Например, детектирую я пешеходов и авто на кадре. И их левая координата уходит в минус, если в кадре видна только часть автомобиля. N>5. Далее знаковые становятся удобнее, когда происходит преобразование в другие системы координат. В твоей экранной системе координаты только положительные, ты рисуешь график в декартовой и числа внезапно становятся отрицательными. N>6. Даже яркость пикселя, которая чаще всего от 0 до 255 и представлена в uchar при манипуляциях с яркостью легко вылезает за пределы типа вверх и вниз, поэтому тут либо ставить кучу проверок, либо при манипуляциях кастовать в int, а потом обратно. Хотя тут больше есть ограничение на тип, но если сделать его и uint64, легче не станет.
N>Получается, что большая часть моих кейсов сводится к тому, что естественные ограничения на беззнаковость идут к херам при вычислениях с этими типами. Насколько размер одного контейнера больше второго? Нельзя просто так взять и вычесть! Надо написать if (v1.size() > v2.size())... N>Ну куда такое годится?
Таки да. Не особый фанат или знаток Java — но, насколько я помню, там типы — только знаковые из-за соображений безопасности (переполнения и т.п.).
Лично я сам использую С++ и использую беззнаковые типы, где это только можно. И по-опыту скажу — что никаких особых преимуществ это не дает,
часто делаю размер беззнаковым только потому, чтобы кто-то другой не стал бы тыкать пальцами, и "так надо".
ЕМ>Откуда такое пристрастие, кроме как от лени? Вроде как сколько-нибудь массовых процессоров, где беззнаковые целые поддерживались бы ограниченно, не существует. Есть в этом хоть какое-то рациональное зерно?
К ранеесказанному добавлю ещё один кейс.
Индекс в массиве это полноценная сущность БД. Используется вместо указателей.
В этом случае отрицательные значения используются для обозначения невалидных объектов (у нас это -1) и для каких-нибудь специальных констант.
_____________________
С уважением,
Stanislav V. Zudin
Не знаю как вообще, но скажу за себя, почему не очень часто использую unsigned.
Во-первых, повидал кучу багов в коде других, когда это приводило к ошибкам, а чтоб ошибки не было, надо было доп условия ставить.
Во-вторых, иногда нужно не-валидное значение чего-то, что по смыслу неотрицательно. И для этого я лично использую «-1». И если переменная равна ему, то значит значение невалидное. Такая штука с unsigned не проканает, если не вводить всякие magic digits конечно.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Откуда такое пристрастие, кроме как от лени? Вроде как сколько-нибудь массовых процессоров, где беззнаковые целые поддерживались бы ограниченно, не существует. Есть в этом хоть какое-то рациональное зерно?
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Даже во многих современных программах на C++ часто вижу int/short/long там, где по смыслу должно быть беззнаковое целое. А в ранних программах знаковые целые вообще использовались везде, где было технически возможно. Даже в классической книге Кернигана/Ритчи множество примеров, где счетчики, индексы и прочие имеют знаковый тип. В виндовых SDK, где знаковость в основном используется адекватно, все равно регулярно встречаются знаковые параметры размеров, количеств и прочего, где не используются отрицательные значения для особых случаев.
ЕМ>Откуда такое пристрастие, кроме как от лени? Вроде как сколько-нибудь массовых процессоров, где беззнаковые целые поддерживались бы ограниченно, не существует. Есть в этом хоть какое-то рациональное зерно?
Здравствуйте, Шахтер, Вы писали:
Ш>Это из-за багов в генах.
Поясни. Тебе выкатили простыню из кучи случаев, где отсутствие знака в типе переменной провоцирует ошибки. Ты молча влепил минус без обоснования. Давай, поясняй.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Откуда такое пристрастие, кроме как от лени? Вроде как сколько-нибудь массовых процессоров, где беззнаковые целые поддерживались бы ограниченно, не существует. Есть в этом хоть какое-то рациональное зерно?
Операции, в которых участвуют исключительно знаковые аргументы, производятся по правилам обычной школьной арифметики (mod 2^31 держим в уме, конечно)
Операции, в которых используются исключительно беззнаковые аргументы, хороши, пока дело ограничивается арифметикой на уровне начальной школы — до того момента, когда в школе начинают изучать отрицательные числа. Вопрос о том, можно ли от 1 отнять 2, и что при этом будет, блокируется Марией Ивановной со словами "об этом вам расскажут в 5 классе"
Операции, в которых одновременно используются знаковые и беззнаковые аргументы, требуют внимательного рассмотрения в каждом случае — иначе можно такое получить, что не дай бог. Причем самое скверное, что получить это можно иногда в 0.01% случаев, так что и не протестируешь порой как следует.
Резюме — программистам, имеющим образование выше начальной школы, лучше использовать знаковые аргументы и не париться.
Исключение их правила : использование целого как битовой шкалы. В этом случае, естественно, лучше без знака, так как арифметики тут не предвидится.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, T4r4sB, Вы писали:
TB>>Ты на беззнаках даже тупо от ЭН до нуля проитерироваться не можешь без дополнительного бубна.
R>А в чем проблема?
i--, заменяющее сразу два блока из заголовка for? Мы вам перезвоним, ога.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Даже во многих современных программах на C++ часто вижу int/short/long там, где по смыслу должно быть беззнаковое целое. А в ранних программах знаковые целые вообще использовались везде, где было технически возможно. Даже в классической книге Кернигана/Ритчи множество примеров, где счетчики, индексы и прочие имеют знаковый тип. В виндовых SDK, где знаковость в основном используется адекватно, все равно регулярно встречаются знаковые параметры размеров, количеств и прочего, где не используются отрицательные значения для особых случаев.
ЕМ>Откуда такое пристрастие, кроме как от лени? Вроде как сколько-нибудь массовых процессоров, где беззнаковые целые поддерживались бы ограниченно, не существует. Есть в этом хоть какое-то рациональное зерно?
Откуда эта лютая любовь к без знаковым целым? От жадности? Зачем использовать без знаковое целое где можно использовть обычный int или very long long. Только ради экономии 1-го бита? В большнистве случаев целые числа используются с запасом по разрядной сетке иногда с эпичемким запасом. В редких случаях бывает удобно использовать беззнаковые числа, например при сравнении знаковых (unsigned)(x-x0) < (unsigned)width вместо двух сравнений достаточно 1-го и при битовых сдвигах. В остальных случаях знаковых более чем достаточно. Более того минимальное отрицательное число можно использовать как признак отсутствия значения. if (x && x==-x) return novalue();
ps: меня больше огорчает всеобщее пристрастие к условию выхода из цикла for(size_t i=0;i!=end;++i){} где исключается одна точка, вместо for(size_t i=0;i<end;++i){} где запрещаются все недопустимые значения.