Что: 66e846326ec104c644c977d7be848d4e4fe0b729
Когда: 2024-10-22 11:01:35+03:00
------------------------------------------------------------------------
Темы: c
------------------------------------------------------------------------
Снова про решения при разработке на Си

В прошлых проектах я всегда для всех структур и enum-ов делал typedef-ы.
Мне казалось, что без них как-то не очень отображаются человекочитаемые
имена в LLDB. Но то ли времена поменялись, то ли я чего напутал, но
сейчас проблем нигде не заметил. И стал указывать просто "struct XXX" и
"enum XXX".

В 5f1645eb510d76ffb07c07fa09bffdea01959c03 и
81768895c53201dd862f7164ded5c7a90de6c55b как-то заходила речь про тип
переменных для указания индексов в массивах и размерах данных. С одной
стороны много говорят про то, что с знаковым типом сильно проще, ибо при
переполнении он станет отрицательным. С беззнаковым будет использоваться
арифметика с модулями. И я склонялся к этому варианту и решению,
использованию каких-нибудь ptrdiff_t.

Однако, переполнение signed числа является undefined behaviour! Тогда
как переполнение unsigned чётко и понятно определено. На практике, так
как у нас 2's complement, поведение *скорее всего* будет определено, но
компилятор из-за UB может и проблем подкинуть из-за оптимизации которую
он решил проделать. Есть -fwrapv (3f2f2ebd3ca7c13eaa4f4bdb0043032d0daeac03)
опция, которая позволяет форсировать строгое поведение при переполнении
signed, но оно закрывает путь к некоторым возможным оптимизациям
(судя по тому что пишут).

Во многих случаях, что с signed, что с unsigned -- надо проверять не
произошло ли переполнение. Это в любом случае if-ы. Так что у меня выбор
свёлся либо к: использовать -fwrapv, либо без него. Без него означает
меньше требований к флагам компиляции и это даёт возможность
использовать на один бит больше. Так что для размеров я уже точно без
сомнений считаю, что в Си нужен size_t, не забывая про проверки
переполнения. В ЯПах без UB для signed переполнений, типа Go,
использовать signed тип, если не критично что один бит теряется.
Собственно, Go и использует int для len() и индексов массивов.

------------------------------------------------------------------------
оставить комментарий: mailto:comment@blog.stargrave.org?subject=Re:%20%D0%A1%D0%BD%D0%BE%D0%B2%D0%B0%20%D0%BF%D1%80%D0%BE%20%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BF%D1%80%D0%B8%20%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B5%20%D0%BD%D0%B0%20%D0%A1%D0%B8%20%2866e846326ec104c644c977d7be848d4e4fe0b729%29

------------------------------------------------------------------------
комментарий 0:
From: David Rabkin
Date: 2024-10-26 12:35:23Z

В Си99 typedef-ы нужны для алиасов, чтобы не писать struct в типах
переменных, вот тут подробно:
 https://stackoverflow.com/questions/1675351/typedef-struct-vs-struct-definitions

Может, что поменялось в стандарте за четверть века?

Опять же, в Си99 size_t рекомендован для размеров и индексов. Зачем он
иначе нужен? А дискуссия про типы индекса интересная, да.

------------------------------------------------------------------------
комментарий 1:
From: Sergey Matveev
Date: 2024-10-26 20:35:49Z

*** David Rabkin [2024-10-26 15:32]:
>В Си99 typedef-ы нужны для алиасов [...]

Это то понятно. Я прежде так и делал. Но тут вот убедился, что не так уж
и сложно писать "struct" рядом со структурами. Оно не напрягает.

>Опять же, в Си99 size_t рекомендован для размеров и индексов. Зачем он
>иначе нужен? А дискуссия про типы индекса интересная, да.

Рекомендован или стандартизован -- не значит что это обязательно
адекватно и продуманно. В Си есть и wchar_t, что точно не стоит
использовать.

------------------------------------------------------------------------
Сгенерирован: SGBlog 0.34.0