170 похожих чатов

Давненько не было дискуссии про инты. Ну, или я не

видел. Пришёл на новую работу, и тут повсеместно используется size_t для того, чтобы "что-то посчитать", т.е. в качестве "целочисленного типа общего назначения". Я полностью согласен с Джоном Калбом, что подобный тип должен быть знаковым (https://youtu.be/wvtFGa6XJDU). Так что size_t - плохой выбор. Долгое время я для этих целей использовал просто int, но т.к. пишу код для 64-битных процессоров, более естественным (и более эффективным: https://gcc.godbolt.org/z/fMEvsn6aE) является int64_t или даже ещё лучше intptr_t.

Но вот беда - его неудобно печатать. Ну то есть надо тянуться пальцами до "64", а потом ещё и зажимать шифт для подчёркивания. К тому же, "64" звучит как некая деталь реализации. Я хочу просто какой-то наиболее подходящий в общем случае целочисленный тип. В котором можно что-то посчитать, поумножать и повычитать, который можно использовать для индексирования массива. Вот если бы я что-то сериализовывал - тогда да, можно было бы явно указать, что там 64 бита. А так - мме.

Вот я бы сделал #define int intptr_t, но мне нравятся мои ноги, не хочу отстреливать. Можно сделать using Int = intptr_t. Но это выглядит как какой-то шибко умный тип. Есть предложение using word = intptr_t, что мне пока кажется наиболее интересным. Но может будут ещё какие-то идеи? Что вообще думаете по этому поводу?

52 ответов

17 просмотров

не совсем понял, какой смысл использовать знаковый тип для индексации массива?

1) удивлен, что вы ни разу не упомянули ptrdiff_t 2) 64-битные инты точно не самый эффективный тип для арифметики на 64-битных архитектурах, так как результат сложения или перемножения двух таких переменных в общем случае не умещается в int64_t

Массивы индексировать — size_t или ssize_t, мне кажется. Просто какое-то не очень большое целое — int. Я бы не усложнял. Но и оптимизациями ассемблера не занимался и не особо шарю

Зачем знаковый размер?

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

Михаил, как думаешь, почему в языке 10 целочисленных типов, а не один? Правильно, чтобы в разных случаях использовать наиболее подходящий для этого случая тип данных. Вопрос "Я хочу просто какой-то наиболее подходящий в общем случае целочисленный тип." - он плохой уже сам по себе. В каждом случае надо подбирать подходящий для этого случая тип, а не ВООБЩЕ.

Mikhail-Matrosov Автор вопроса
Oleg Linkin
не совсем понял, какой смысл использовать знаковый...

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

Mikhail-Matrosov Автор вопроса
Mikhail-Matrosov Автор вопроса
Vlad
1) удивлен, что вы ни разу не упомянули ptrdiff_t ...

2 - не понял, так результат сложения/умножения чисел в любом типе не обязан умещаться в этот тип

Mikhail-Matrosov Автор вопроса
Mikhail-Matrosov Автор вопроса
Ilya Zviagin
Михаил, как думаешь, почему в языке 10 целочисленн...

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

Mikhail-Matrosov Автор вопроса
Ilya Zviagin
Как-будто что-то плохое...

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

Mikhail-Matrosov Автор вопроса
Mikhail Matrosov
intptr_t по умолчанию

По умолчанию где, куда?

Mikhail-Matrosov Автор вопроса
Ilya Zviagin
По умолчанию где, куда?

Когда мне нужно бежать по массиву (если нужен индекс), считать какое-то количество (подлкючений, пользователей), делать арифметику любого рода, сравнивать числа

Mikhail Matrosov
о да, очень плохое. и создатели языка и библиотеки...

если бы они еще что-то с этим сделали, помимо ssize

Mikhail Matrosov
Когда мне нужно бежать по массиву (если нужен инде...

Ну, ты можешь свой код как угодно писать, да, только без UB желательно.

Vlad
[p1491]

P1491R0: Don’t add to the signed/unsigned mess (by Bjarne Stroustrup) (2019-02-14) (Related: GitHub issue)

Знаковый тип крайне плохо выражает намерения программиста — при каждой индексации есть сомнение вида "а не могло ли нам придти отрицательное число как-нибудь?". Если же тип беззнаковый, такое сомнение возникает куда реже (на моём опыте) — в местах явного каста (не забываем про -Wall -Werror) Т.е. при использовании знаковых мы момент валидации индексов откладываем до момента непосредственного использования, которых, во-первых, больше, во-вторых тут зачастую уже становится непонятно, откуда нам пришли невалидные значения и как исправлять ошибку

Mikhail-Matrosov Автор вопроса
Ofee Oficsu
Знаковый тип крайне плохо выражает намерения прогр...

Это иллюзия безопаности. Джон как раз объясняет в видео, почему это не так. Если кратко - то у тебя никогда нет уверенности, что в твоём беззнаковом типена самом деле не лежит -1, перевёрнутый в MAX. Но ты никак этого не сможшеь проверить. А если тип знаковый, ты хотя бы сможешь это увидеть.

Mikhail Matrosov
Это иллюзия безопаности. Джон как раз объясняет в ...

А откуда уверенность, что в знаковом int64_t не лежит 2^63 - 1?

Mikhail-Matrosov Автор вопроса
Sergey Skvortsov
А откуда уверенность, что в знаковом int64_t не ле...

переполнения нуля вниз - гораздо более частое явление, чем переполнения 2^63 вверх

Я помню этот видос, сумашедший довольно...

Mikhail Matrosov
переполнения нуля вниз - гораздо более частое явле...

Проверки на отрицательность для отлова ошибок — симптоматическое лечение

Mikhail Matrosov
Это иллюзия безопаности. Джон как раз объясняет в ...

Там -1 может придти либо из литерала и это довольно просто отследить, либо при любых подозрительных операциях с беззнаковым типом, на которые обязательно пожалуется компилятор и потребует явных кастов, которые заметить куда как легче Различные проявления UB я в расчёт тут не беру, тут сложно и с беззнаковыми, и со знаковыми

Mikhail-Matrosov Автор вопроса
Sergey Skvortsov
Проверки на отрицательность для отлова ошибок — си...

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

Mikhail-Matrosov Автор вопроса
Ofee Oficsu
Там -1 может придти либо из литерала и это довольн...

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

Mikhail Matrosov
если вычитаешь два беззнаковых, и второе оказывает...

А если вычитаешь два беззнаковых и результат оказывается больше знакового?

если уж совсем честно писать, то std::intptr_t (акцент на std::)

Mikhail Matrosov
эмм. непонятно. ну самый лучший вариант - не делат...

Вы либо так же делаете range check (и одной проверкой, а не двумя), либо любое значение подходит

Mikhail-Matrosov Автор вопроса
Max Kolesnikov
А если вычитаешь два беззнаковых и результат оказы...

тогда мы работаем с оцень большими числами. утверждение в том, что обычно мы работаем с числами, которые гораздо меньше 64 бит

Mikhail-Matrosov Автор вопроса
Alexander Karaev
если уж совсем честно писать, то std::intptr_t (ак...

это академизм ) intptr_t если он есть, то обязан совпадать с std::intptr_t. а если его нет - то компилятор тебе быстро об этом скажет )

Mikhail-Matrosov Автор вопроса
Sergey Skvortsov
Вы либо так же делаете range check (и одной провер...

какой range check я сделаю для беззнакового типа?

Mikhail-Matrosov Автор вопроса
Sergey Skvortsov
i < size()

не всегда известен size(). может вы вычисляете как раз новый size()

Mikhail-Matrosov Автор вопроса
Sergey Skvortsov
size() не бывает (size_t)-1 ?

в смысле бывает ли size() равен max_size_t-1? на 64 битах не бывает. если вам не хватает 63 бит для ваших массивов - вы делаете что-то крайне специфическое. ну, по сравнению с моим доменом

Mikhail Matrosov
если вычитаешь два беззнаковых, и второе оказывает...

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

Mikhail-Matrosov Автор вопроса
Ofee Oficsu
В таком случае вы, вероятнее, заинтересованы не в ...

с трудом могу себе представить такую диагностику. ну и речь всё-таки не об этом

Mikhail Matrosov
с трудом могу себе представить такую диагностику. ...

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

Vlad
1) удивлен, что вы ни разу не упомянули ptrdiff_t ...

А можно поподробнее о эффективности? Потому что я вижу разницу только в случае imul с одним операндом: https://uops.info/table.html?search=imul&cb_lat=on&cb_tp=on&cb_uops=on&cb_ports=on&cb_SKL=on&cb_measurements=on&cb_doc=on&cb_base=on

magras
А можно поподробнее о эффективности? Потому что я ...

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

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

Беззнаковые действительно ограничивают возможности оптимизации компилятора из-за фиксированного поведения при переполнении. Речь об этом? Но вроде это никак не связано с размерами типов.

magras
Беззнаковые действительно ограничивают возможности...

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

Vlad
кажется, если пользоваться беззнаковыми типами нат...

хм. Это интересное наблюдение, что u64 даст тот же эффект, что i32. Спасибо.

Похожие вопросы

Обсуждают сегодня

а через ESC-код ?
Alexey Kulakov
29
30500 за редактор? )
Владимир
47
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
13
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
6
в JclConsole объявлено так: function CtrlHandler(CtrlType: DWORD): BOOL; stdcall; - где ваше объявление с stdcall? у вас на картинке нет stdcall
Karagy
8
Ребят в СИ можно реализовать ООП?
Николай
33
Вот еще странный косяк, подскажите как бороться. Я git clone сделал себе всего embassy и примеры там запускаю. Всё хорошо. Но вот решил в cargo.toml зависимости не как в приме...
Lukutin R2AJP
2
program test; {$mode delphi} procedure proc(v: int32); overload; begin end; procedure proc(v: int64); overload; begin end; var x: uint64; begin proc(x); end. Уж не знаю...
notme
6
Карта сайта