[О блоге] [наверх] [пред] [2024-10-22 11:01:35+03:00] [66e846326ec104c644c977d7be848d4e4fe0b729]
Темы: [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() и индексов массивов.

    [оставить комментарий]
    комментарий 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, что точно не стоит
    использовать.