До стандарта еще. Первое издание книги Страуструпа где-то 85 года, там уже было все стабильно относительно, а к моменту ARM(1990 вышла вроде) уже не было существенных изменений в синтаксисе.
Я ржавчину под виндой не использую, так что личными впечатлениями поделиться не могу. Меня сейчас интересует работа под линуксом (этой платформе достается больше всего поддержки) и андроид (тут все ожидаемо так себе, с андроидом по другому и быть не может. Но, если есть желание, то пользоваться можно).
Насколько мне известно, ржавчинва под виндой есть, даже с официальным установщиком, который сразу и cargo ставит. Есть всякие мелкие косяки, они менее приоритетны, чем ошибки под линуском или яблоками, но, в целом, жить вполне себе можно. Точно знаю, что https://github.com/tomaka пользуется ржавчиной под виндой для каких-то поделок. Собственно, его glutin тестируется не только в travis-ci, но и под виндой в appveyor: https://github.com/tomaka/glutin/blob/master/appveyor.yml
Мне нравится, как в сишке сделано. unsigned/int - платформозависимы(как и short, long и long long), а для остального - тайпдефчики. size_t, ptrdiff_t, intptr_t/uintptr_t, int<размер-в-битах>_t/uint<размер-в-битах>_t. Просто и логично.
Зачем вообще платформозависимый тип? Почему бы не использовать везде тот тип, который имеет подходящую размерность? Для адресации памяти size_t нужен, это понятно. А во всех остальных случаях зачем?
На разных платформах будет разный набор наиболее эффективных машинных операций над целыми числами, отсутствие привязки к размеру дает компилятору дополнительные возможности. А какой смысл использовать именно 32битные значения, когда тебе нет дела до размера?
Мне нравится, как в сишке сделано. unsigned/int - платформозависимы(как и short, long и long long), а для остального - тайпдефчики. size_t, ptrdiff_t, intptr_t/uintptr_t, int<размер-в-битах>_t/uint<размер-в-битах>_t. Просто и логично.
Уже ответили, присоединяюсь: зачем тебе хранить обычные числа в переменной платформозависимого размера? Я не вижу у этого достоинств, только недостаток: разное поведение на разных платформах. Отлаживали на 64, а на 32 внезапно начали появлться странные ошибки в неожиданных местах.
Ну вот и надо было назвать intptr/uintptr, а обычные int/uint сделать как в Си.
Ну, если ты читал RFC, то знаешь, что одним из вариантов-кандидатов был iptr/uptr. Довольно близко к intptr, только ближе к схеме именования типов в ржавчине - i8, i16, i32, ...
Недостатки этого варианта, собственно:
Cons: C/C++ have intptr_t/uintptr_t, which are typically only used for storing casted pointer values. We don't want people to confuse the Rust types with the C/C++ ones, as the Rust ones have more typical use cases. Also, people may wonder why all data structures have «pointers» in their method signatures. Besides the «funny-looking» aspect, the names may have an incorrect «pointer fiddling and unsafe staff» connotation there, as ptr isn't usually seen in safe Rust code.
Размеры/индексы и размеры указателя несколько разные вещи. По крайней мере для некоторых архитектур. А rust ведь хочет быть системным.
Может, я туплю, но не понимаю, в каком случае текущая схема в ржавчине может помешать портированию? Оно ж как раз этот фактор и учитывает и поэтому меня поправили.
На разных платформах будет разный набор наиболее эффективных машинных операций над целыми числами, отсутствие привязки к размеру дает компилятору дополнительные возможности. А какой смысл использовать именно 32битные значения, когда тебе нет дела до размера?
Я не эксперт по процессорам, но не думаю, что на более-менее распространенных архитектурах операции над числами меньшего размера значительно медленнее операций над числами большего размера (если я ошибаюсь, то буду рад увидеть ссылки :) ). Зато, если использовать переменные меньшего размера, их больше влезет в кэш. В общем, если я не прав, то тоже хочу ссылок по этому поводу, буду рад просвятиться.
На разных платформах будет разный набор наиболее эффективных машинных операций над целыми числами, отсутствие привязки к размеру дает компилятору дополнительные возможности.
Сомнительно.
А какой смысл использовать именно 32битные значения, когда тебе нет дела до размера?
Так не бывает. Как думаешь – сколько программ на C сломаются, если определить int равный одному байту (8 битам)?
Как думаешь – сколько программ на C сломаются, если определить int равный одному байту (8 битам)?
Эм, int же не может быть меньше 16 бит по стандарту, он же снизу ограничен по размеру. Но, уверен, даже если int будет 16 бит, то много обычных программ поломается.
Потому, что на разных платформах отличаются даже размеры байтов. Не говоря уже о размере слова. Если ты хочешь оставаться в рамках системного языка, а точный размер тебе не нужен, то логично использовать размер по умолчанию для данной платформы.
зачем тебе хранить обычные числа в переменной платформозависимого размера?
Для сохранения близости к платформе и «естественности» поведения на ней. Независимо от нее.
Не хочешь - не храни, есть типы с фиксированным размером.
Я так понял, что в Rust вообще нет теперь int и uint, так чем бы они тебе помешали, если были бы платформозависимыми? ;)
Так что вполне логично иметь:
int/uint - для предоставления достаточно эффективных типов на той платформе, под которую компилируем.
isize/usize - для типов, хранящих платформозависимые размеры
iptr/uptr - для типов, достаточных для хранения указателей/смещений между указателями.
iРазмер/uРазмер - для типов фиксированной длины(и да, возможно, что на данной платформе какого-то из таких типов не будет - и это тоже нормально)
Отлаживали на 64, а на 32 внезапно начали появлться странные ошибки в неожиданных местах.
int обычно оставляют 32битным.
Может, я туплю, но не понимаю, в каком случае текущая схема в ржавчине может помешать портированию? Оно ж как раз этот фактор и учитывает и поэтому меня поправили.
Актуальный пример, наверное, не приведу, но если мы вспомним 16 битные процессоры с сегментами, то для размеров там вполне было достаточно 16 бит(достаточно для размеров в рамках сегмента), а вот указатели требовали сегмент + смещение.
Потому, что на разных платформах отличаются даже размеры байтов. Не говоря уже о размере слова. Если ты хочешь оставаться в рамках системного языка, а точный размер тебе не нужен, то логично использовать размер по умолчанию для данной платформы.
Если тебе размер не важен, используй bool. Если важен, используй минимально допустимый тип. Зачем нужен некий загадочный размер по умолчанию, про который мы знаем только то, что он не меньше двух байтов? В каких случаях он даст выигрыш?
Довольно интересно смотреть через призму времени, как они от @5i пришли к Rc::new(5i), а теперь и от ~3i через box 3i пришли к такому же крестоподобному Box::new(5i). Не говорю, что это плохо, просто забавно.
Зачем нужен некий загадочный размер по умолчанию, про который мы знаем только то, что он не меньше двух байтов
Затем, что платформа не обязана в этом случае поддерживать int16_t. В ней просто должен быть тип, который больше или равен int16_t. Ты, конечно, можешь предложить использовать мне int_least16_t, но зачем мне эти подпрыгивания на ровном месте?
Кроме того, код с int может корректно работать на одной платформе и на другой, просто там, где он больше, наш софт будет способен обрабатывать, например, больше данных. Будешь использовать uint32_t - проиграешь на более слабой платформе, будешь использовать uint16_t, не сможешь выиграть на более сильной.
Актуальный пример, наверное, не приведу, но если мы вспомним 16 битные процессоры с сегментами, то для размеров там вполне было достаточно 16 бит(достаточно для размеров в рамках сегмента), а вот указатели требовали сегмент + смещение.
Вспомним. Не знаю как на других, а на x86 возможность сишечки иметь указатели нестандартного размера не использовали, а обмазывались диалектами с __far, __near и т.п.
Вспомним. Не знаю как на других, а на x86 возможность сишечки иметь указатели нестандартного размера не использовали, а обмазывались диалектами с __far, __near и т.п.
Это да. Но речь шла о возможной разницы между size_t и uintptr_t. В Rust будет только один тип и для того, и для другого, как я понял.
Никто тебе не мешает использовать соответствующие typedef из stdint.h для типов фиксированного размера. В большинстве случаев никакого вреда от int не будет. Для системного языка, работающего на разных платформах, логично не делать встроенные типы с захардкоженным размером.
Никто тебе не мешает использовать соответствующие typedef из stdint.h для типов фиксированного размера.
Также мне никто не мешает писать код сразу без ошибок. И никто не помешает тонким ценителям в Rust определить любимый инт, зависимый от платформы, и использовать его при необходимости.
В большинстве случаев никакого вреда от int не будет.
В большинстве случаев от инта один вред, т.к. его используют неправильно, часто вместо size_t/ptrdiff_t, делают допущения о его размере, и т.д. В сишечке использование инта еще можно понять, т.к. с ним не надо думать о integer promotion в каждом выражении, в Rust - нет.
Для системного языка, работающего на разных платформах, логично не делать встроенные типы с захардкоженным размером.
Наоборот, логично их сделать. Надежность кода важнее скорости, типы с одинаковыми лимитами это прекрасно, особенно для портирования. Один С уже есть, второго не нужно.
чем тебя uint16_t не устраивает кроме дурацкого названия?
А чем он лучше int?
Тем, что про него всё чётко известно.
int16_t не обязан вообще поддерживаться данной платформой.
Обязан.
Чем тебя не устраивает int?
Тем, что это не конкретный тип и про него ничего не известно. Давай введём randomint, который будет иметь случайный размер от 0.5 до 128 байтов, определяемый в момент компиляции программы, чтобы было интересней?
Ну если тебе всё равно, сколько значений может принимать этот тип, значит двух значений хватит, больше – излишества.
Затем, что платформа не обязана в этом случае поддерживать int16_t. В ней просто должен быть тип, который больше или равен int16_t. Ты, конечно, можешь предложить использовать мне int_least16_t, но зачем мне эти подпрыгивания на ровном месте?
Не бывает платформы, которая не поддерживает 16-битовые числа. На абсолютно любой тьюринг-полной платформе можно реализовать поддержку чисел любой битности.
Кроме того, код с int может корректно работать на одной платформе и на другой, просто там, где он больше, наш софт будет способен обрабатывать, например, больше данных.
А там, где он меньше, наш софт вообще не будет работать. Так что ли? Как это «больше данных»? Сколько может данных софт обрабатывать – может зависеть от памяти, от скорости процессора, от скорости ввода-вывода, но никак не от размера int-а.
Будешь использовать uint32_t - проиграешь на более слабой платформе, будешь использовать uint16_t, не сможешь выиграть на более сильной.
Также мне никто не мешает писать код сразу без ошибок. И никто не помешает тонким ценителям в Rust определить любимый инт, зависимый от платформы, и использовать его при необходимости.
Наличие в стандартной библиотеке таких типов меня бы устроило.
Скорее всего у rust просто не будет многих платформ...
Надежность кода важнее скорости
В системном языке программист должен решать, что ему важнее в данном конкретном случае.
типы с одинаковыми лимитами это прекрасно, особенно для портирования.
Эти типы никто не убирает.
Один С уже есть, второго не нужно.
В итоге придем к тому, что rust полноценной заменой си быть не может даже в перспективе. Это печально.
Кстати, подумайте над тем, сколько лет Си и сколько архитектур изменилось за это время. Если бы во время создания в си применялись подобные решения, связанные с захардкоженностью тех или иных вещей, в том числе и размеров, то вряд ли бы это положительно сказалось на его долговечности.
Если int явно вмещает хотя бы 16 бит, то чем тебя не устраивает ситуация, когда он будет занимать больше? Зачем ограничивать и верхнюю планку тоже(кроме случаев, когда это важно - сетевые пакеты и пр.)?
Обязан.
Нет, не обязан. Платформа может его не поддерживать и тогда этого типа не будет.
7.20.1.1 Exact-width integer types
1 The typedef name intN_t
designates a signed integer type with width N, no padding
bits, and a two’s complement representation. Thus, int8_t denotes such a signed integer type with a width of exactly 8 bits.
2 The typedef name uintN_t designates an unsigned integer type with width N and no padding bits. Thus, uint24_t denotes such an unsigned integer type with a width of exactly 24 bits.
3 These types are optional. However, if an implementation provides integer types with widths of 8, 16, 32, or 64 bits, no padding bits, and (for the signed types) that have a two’s complement representation, it shall define the corresponding typedef names.
Скорее всего у rust просто не будет многих платформ...
Да и плевать на те платформы, С на платформах с особой атмосферой тоже нет - вместо него имеется диалект С, хорошо если совместимый с каким-нибудь стандартом.
В системном языке программист должен решать, что ему важнее в данном конкретном случае.
За нас уже решили, выдав нам С. Вы, может, из того поколения, которое выбирало языки, у меня был выбор из «большой единицы». Пришло время решить еще раз.
Эти типы никто не убирает.
Эти типы появились только в С99(!) и до последнего времени их не было в компиляторе МС, да и без него уже есть куча легаси с интами.
В итоге придем к тому, что rust полноценной заменой си быть не может даже в перспективе. Это печально.
Полноценный эквивалент С со всей его кривизной нафиг нужен.
Кстати, подумайте над тем, сколько лет Си и сколько архитектур изменилось за это время.
Я отлично вижу что С для системного программирования _уже_ не подходит. Нитей, атомарных операций, барьеров, моделей памяти в С не было до последнего времени (и это язык для системного программирования!), без ассемблерных вставок управлять контекстом - нельзя, доступа к регистрам нет, сделать позиционно-независимую функцию и скопировать ее в другой блок памяти в рамках стандарта - невозможно, и т.д, и т.п.
Если бы во время создания в си применялись подобные решения, связанные с захардкоженностью тех или иных вещей, в том числе и размеров, то вряд ли бы это положительно сказалось на его долговечности.
Нет, только не это UB снова. Есть тип для указателя, добавить еще тип машинного слова для эстетских архитектур, а «не меньше 16, натурального для машины, но на 64 разрядах 32 для легаси» типа еще раз не надо.