LINUX.ORG.RU

Проект на чистом Си

 , , ,


6

13

Камрады, всем доборый день!

Решил тряхнуть стариной, написать кое-что полезное для себя и таких же упоротых личностей. Заодно вспомнить Си (который без «крестов»). Естественно, хочется сделать «красиво, модно, молодёжно» и удобно. Вопрос - как проекты на Си принято начинать в 2024? Ну там пакетные менеджеры (а они вообще есть?), линтеры и прочее счастье. Какой стандарт сейчас считается «правильным» для использования и какую литературку/доку по нему почитать? Буду благодарен, если покидаетесь статьями или книгами.

Ответ на: комментарий от cumvillain

каждый второй проект пердолит свои строки.

А без разных видов строк нигде не обойтись. Как минимум потому что надо взаимодействовать с другим софтом/библиотеками,в которых своё понятие о строках и чаще всего оно сишное. Особенно если это какая-то специализированная библиотека для работы с чем-то не на каждом шагу встречающимся. Она скорее всего будет на Си и строки сишные. То есть или писать «переходник» под другой язык с конвертацией строк туда-сюда, или всю библиотеку переписывать на этот язык. Но во втором случае может оказаться что сишные строки приходят с еще более низкого уровня,какого-нибудь протокола обмена с железом например.

watchcat382
()
Ответ на: комментарий от watchcat382

Так старые файлы удалять надо перед запуском reconfigure.

А зачем мне тогда система сборки если она не выполняет своей главной задачи - пересобрать только то, что не соответствует новой конфигурации?
Если мы скажем, что системе сборки дозволено пересобирать всё на любой чих, то может вместо неё просто напишем sh скрипт, вызывающий gcc для каждого файла?
Нет, я понимаю, если бы систем, которые с этим справляются не было, но waf справляется, худо-бедно даже cmake справляется, kbuild справляется. Думаю, когда-то и автотулзы должны были справляться, пока не обрасли костылями. Так объясните пожалуйста, что у meson за эксклюзивное право такое не трекать зависимости в изменившейся конфигурации???

mittorn ★★★★★
()

Ну там пакетные менеджеры (а они вообще есть?)

не нужно. Если пилишь библиотеку - подумай, как ее будут подключать к проектам. Либо с помощью pkg-config, либо с помощью cmake. В идеале вообще написать header-only.

Система сборки - cmake самая распространенная. Если правильно ее использовать, то не будет никаких проблем с кросс-компиляцией, с опакечиванием и т.п. Используй современную версию и запили пресеты, чтобы можно было собрать и например протестировать весь проект одной командой.

Попробуй использовать zig cc для кросс-компиляции, хорошая вещь.

Также хорошо настроить CI на github и сразу выкладывать пакеты в релизы, AUR, Homebrew TAP или еще куда. nfpm в помощь.

линтеры и прочее счастье

clang-tidy для статического анализа.

Положи в исходники конфиг для clang-format, чтобы у контрибьюторов не возникало вопросов. Также предусмотри, чтобы система сборки генерировала clang compilation database, чтобы в IDE или редакторе работало автодополнение, goto reference и т.п.

Запили юнит-тесты, самый популярный фреймворк для этого - googletest. Если хочется что-то на чистом Си, то например cmocka. Предусмотри сборку и запуск юнит-тестов под санитайзерами.

Запили документацию. Doxygen для автоматической, scdoc для man-страниц. Кто говорит, что маны не нужны - брешет.

Какой стандарт сейчас считается «правильным» для использования и какую литературку/доку по нему почитать?

Ядро linux перешло на C11 с перспективой на C17. Какой смысл сейчас использовать что-то старее C17 - я не знаю. Хотя, между ними не особо много разницы. Ознакомься с GNU C extensions и смело их используй.

Основной справочный ресурс - https://en.cppreference.com/w/c. К литературке даже от самых авторитетных авторов я бы относился с крайней осторожностью, там часто пишут всякую чушь и просто вредные советы. Лучше думать своей головой, тем более в сишке.

Lrrr ★★★★★
()
Ответ на: комментарий от cumvillain

Тебе постоянно приходится сражаться с комитетом, с компиляторами, с небом > и аллахом.

Не соглашусь. Си сложен для начинающего как раз своей излишней «вольностью». Тот же gcc даже с включенной кучей предупреждений позволяет слишком вольное обращение с типами. «Сражаться» приходится как раз в более строгих языках. Пока не приучишься сразу писать так,чтобы компилятор не ругался. И это избавляет от кучи глупых,но трудноуловимых ошибок.

watchcat382
()
Ответ на: комментарий от dimgel

https://github.com/rui314/mold Mold: A Modern Linker

РЕСПЕКТ (не забросила проект)!

mold is written in C++20, so if you build mold yourself, you will
need a recent version of a C++ compiler and a C++ standard
library. We recommend GCC 10.2 or Clang 12.0.0 (or later) and
libstdc++ 10 or libc++ 7 (or later).

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 2)
Ответ на: комментарий от a1ba

включение -Wextra -Wpedantic которые как по мне только вредят флудом, >который никто не читает.

Писать надо так,чтобы выбранный компилятор не выдавал предупреждений даже на максимальном уровне,а не выключать их или «не читать». Тогда ошибок будет намного меньше. Особенно это касается программирования в одно лицо,когда взгляд замыливается,а попросить посмотреть код некого.

watchcat382
()
Ответ на: комментарий от watchcat382

Не существует людей, умеющих писать на C корректный код в 100% случаев. Мы это уже выяснили, и довольно давно. Их нет. Вообще. Ни одного.

Вооруженные этим знанием мы можем сделать вывод, что надо бы взять что-то другое (тот же zig). Но почему-то люди продолжают с упорством, дострйным лучшего применения, героически класть свои жизни и время на алтарь доказательной базы ущербности языка.

cumvillain
()
Ответ на: комментарий от mittorn

Если мы скажем, что системе сборки дозволено пересобирать всё на любой >чих, то может вместо неё просто напишем sh скрипт, вызывающий gcc для >каждого файла?

Любая из систем сборки сокращает количество работы компилятора в сравнении с sh скриптом,но никто и нигде не сказал что она сократит его до самого минимального минимума. Те же автотулзы например - не сокращают работу после reconfigure,но вполне неплохо сокращают при правках исходника без изменения названий и количества файлов. Когда уже сконфигурировано то можно просто make запускать. Ну а если захотелось что-то слишком глобально поменять и пришлось аж reconfigure запускать - ну извините… Как минимум потому что изменения могут быть такие,которые сложно проанализировать автоматически и понять что точно можно НЕ перекомпилировать.

watchcat382
()
Ответ на: комментарий от watchcat382

добавить -lrt в флаги линковки это такое вот прям глобальное изменение, которое повлияет на исходные объектники?
У меня нет вопросов к изменнениям флагов именно компиляции, это, очевидно, потребует пересборки всех объектников

mittorn ★★★★★
()
Ответ на: комментарий от cumvillain

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

Люди предпочитают пользоваться знакомыми инструментами,даже если они не лучшие. К тому же выгодно писать на том,что способно понять максимальное количество людей - выше шанс что найдутся еще заинтересованные помощники в проекте. Для некоммерческих проектов это весьма актуально - там и так всегда людей не хватает чтобы еще ставить барьер входа в виде малораспространенного языка. А вот Си в той или иной степени знают примерно все.

watchcat382
()
Ответ на: комментарий от mittorn

добавить -lrt в флаги линковки это такое вот прям глобальное изменение, >которое повлияет на исходные объектники?

Я нисколько не спорю с вами что в данном случае сборочная система проявила излишнюю бдительность. Но на мой взгляд это лучше чем если бы она НЕ пересобрала что-нибудь в тех случаях когда это необходимо было сделать. Вспоминается nmake(вариант make от Borland из начала 90х) который попил немало крови тем что периодически забывал что-нибудь пересобрать. Так что если уж система сборки ошибается,то пусть ошибается в сторону излишней работы,а не наоборот.

watchcat382
()
Ответ на: комментарий от watchcat382

даже на максимальном уровне

А смысл мне исправлять, например, лишние точки с запятой?

предупреждений

Предупреждения, повторюсь, никто не читает. Особенно когда их дофига. Сборка или успешна, или нет.

a1ba
()
Последнее исправление: a1ba (всего исправлений: 1)
Ответ на: комментарий от a1ba

А смысл мне исправлять, например, лишние точки с запятой?

Чтобы таким образом «отключить» лишние предупреждения компилятора и они не помешали увидеть по-настоящему нужные предупреждения. Я везде где что-то писал - всегда «отключал» лишние предупреждения именно редактированием кода. Даже если это были какие-то вроде бы очевидные вещи. Зато благодаря включенным флагам отловил множество глупых(иногда и не очень) ошибок и сэкономил время на отладке. Впрочем - я активно писал код в те времена когда средств контроля корректности написанного было очень намного меньше чем сейчас и они были менее эффективны. Поэтому был рад любой помощи со стороны машины.

А уж за точками с запятой в Си следить надо вообще тщательно,чтобы в спешке или по невнимательности не написать что-нибудь типа такого:

if(a>1);
{
    b=b+a;
}

Кстати, gcc без флагов предупреждений глотает такое молча.

watchcat382
()
Ответ на: комментарий от a1ba

Предупреждения, повторюсь, никто не читает. Особенно когда их дофига. >Сборка или успешна, или нет.

Смотря что считать критерием успешности сборки. Если получение работающей программы то сам факт того что она собралась в исполняемый файл еще не означает успешности сборки. Она еще и должна бы работать как задумывалось.

watchcat382
()

https://learnc.info/c/beginners_guide_to_linkers.html Гид по линкерам для начинающих. Часть 1

https://learnc.info/c/beginners_guide_to_linkers2.html Гид по линкерам для начинающих. Часть 2

https://learnc.info/c/ Курс лекций по языку Си

https://sourceforge.net/directory/windows/?q=linker

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 3)
Ответ на: комментарий от cumvillain

Это ваааааще не так.

Всё же распространенность Си, в том числе и в учебном процессе в вузах - явление вполне объективное. Поэтому понять написанное на Си могут действительно большинство тех кто хоть что-то знает о программировании. Мы же не о профессиональных программистах говорим. Напомню,что эту тему начал человек словами «хочу вспомнить Си». То есть он Си когда-то изучал и вероятно использовал,но ежедневным кодописательством не занимается. А ведь есть еще и программисты-любители, по аналогии с радиолюбителями. Я вот например последние полтора десятка лет таковым и являюсь. Ожидать от таких знания новых языков с высоким уровнем сложности не приходится.

watchcat382
()
Ответ на: комментарий от alysnix

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

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

tiinn ★★★★★
()

Перепиши учебные эмуляторы MARS и RARS. Из книг посоветую почитать «Язык С в XXI веке» - хорошая книжка для того, чтобы прочувствовать сишечную среду. Стандарт ? - бери C99 или лучше C11, поддержка достаточная, сишка даже в новых стандартах довольно консервативна - ничего особо не потеряешь, но плюшки получаешь. Систему сборки не подскажу, лично я бы взял premake5 для генерации файлов сборки, а из инструментов - силанговсий статический анализатор, valgrind и конечно gdb(лично я предпочитаю обёртку gf с гитхаба). Дальше всё зависит от

AKonia ★★
()
Ответ на: комментарий от watchcat382

Полностью согласен! Единственная проблема в том,что если программа становится большой то фактически вручную следить за распределением памяти (контроля-то никакого нет) - становится утомительно.

Так-таки и единственная проблема? А как же

Даже -Wall -Wextra -Wpedantic не включает вообще всё. Читай документацию на GCC, посмотри какие полезны и включай их вручную, постепенно исправляя класс потенциальных ошибок.

tiinn ★★★★★
()
Ответ на: комментарий от watchcat382

Писать надо так,чтобы выбранный компилятор не выдавал предупреждений даже на максимальном уровне,а не выключать их или «не читать».

Лично я иногда юзаю statement expressions, «a ?: b», а в сгенерированном коде – массивы меток. Соответственно, лично я в гробу видал -Wpedantic. Pedantic – это в первую очередь (а может и в единственную, не помню) контроль на соответствие стандарту. Что автоматически запрещает любые расширения.

dimgel ★★★★★
()
Последнее исправление: dimgel (всего исправлений: 1)
Ответ на: комментарий от watchcat382

но вполне неплохо сокращают при правках исходника без изменения названий и количества файлов

Серьёзно? А какая тулза этого НЕ умеет?

Вспоминается nmake(вариант make от Borland из начала 90х) который попил немало крови тем что периодически забывал что-нибудь пересобрать

А, всё, понял.

tiinn ★★★★★
()
Последнее исправление: tiinn (всего исправлений: 1)
Ответ на: комментарий от tiinn

А как же Даже -Wall -Wextra -Wpedantic не включает вообще всё.

Это если и может быть проблемой,то только для программиста-любителя,который берется за компилятор не слишком часто. Тот, кто пользуется компилятором [почти] ежеденвно - тот знает его особенности на зубок,да не только ключи,а и как там что под капотом работает. Также как я это знал в 90е когда зарабатывал в том числе и написанием кода (еще осциллографом и паяльником).

watchcat382
()
Ответ на: комментарий от tiinn

А какая тулза этого НЕ умеет?

Вы отрезали кусок моей цитаты о том,что сокращать работу компилятора умеет любая система сборки,но вам никто не обещал что она сократит ее до теоретически возможного минимума. Понятно что эффективность систем сборки разная. Но опять не факт что самая эффективная окажется самой удобной для человека-пользователя. Даже скорее может быть наоборот. Пожалуй что сверхтщательным вылизыванием makefile можно добиться максимальной эффективности. Но усилий это потребует изрядных. Тот же cmake - можно назвать более высоким уровнем абстракции,то добавляет удобства человеку,но и работы машине добавляет тоже.

watchcat382
()
Ответ на: комментарий от mittorn

А претензия в том, что она ошибается в обе.

А вот это уже действительно серьезно! И означает непригодность к использованию.

Были как случаи не пересборки чего-то после правок,

Не ожидал что и через три десятка лет традиции вышеупомянутого борландовского nmake живут.

watchcat382
()
Ответ на: комментарий от dimgel

Лично я иногда юзаю statement expressions, «a ?: b», а в сгенерированном >коде – массивы меток.

Если это обусловлено какой-то категорической необходимостью - то это как раз тот случай редкого исключения который подтверждает общее правило. Но я не уверен что задача не решаема более традиционными способами. И если например в олимпиадном программировании всякие трюки это вполне допустимо и даже может быть хорошо, то в рутинном производственном процессе лучше бы от экзотики воздерживаться.

Pedantic – это в первую очередь (а может и в единственную, не помню) >контроль на соответствие стандарту.

В технике соответствие стандарту - это хорошо и правильно. Отступления от стандартов лучше оставить ученым,занимающимся экспериментами.

Что автоматически запрещает любые расширения. Стандартов Си существует несколько. И отличаются они как раз именно входящими в стандарт расширениями. Которые в рамках выбранного стандарта уже не являются его нарушениями и -Wpedantic на них не реагирует.

watchcat382
()
Ответ на: комментарий от watchcat382

Это если и может быть проблемой,то только для программиста-любителя

Ну, в разрезе треда ТСа мы, кажется, именно любителей обсуждаем. И тут вы такой

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

Полностью согласен! Единственная проблема в том,что если программа становится большой

А потом выясняется, что 1) в сях не всё нормуль, 2) проблема далеко не единственная - для программиста-любителя

tiinn ★★★★★
()
Ответ на: комментарий от tiinn

в разрезе треда ТСа мы, кажется, именно любителей обсуждаем. И тут вы >такой

Мало какой любитель (более-менее квалифицированный,не чайник) в одно лицо напишет программу такого размера чтобы «утонуть» своем коде и наделать совсем уж трудноуловимых ошибок в работе с памятью. Как раз именно любители обычно мотивированы изучать используемые инструменты и писать хороший код. Это на работу сейчас популярно «тяп-ляп и в продакшн».

в сях не всё нормуль

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

проблема далеко не единственная - для программиста-любителя

Как программист-любитель в течении последних полутора десятков лет - могу сказать что при разработке так сказать «соло» основная проблема это придумать хорошую архитектуру своей программы. Не знаю,может быть сейчас этому учат,а вот во времена моей учебы этот вопрос как-то упускался преподавателями. Да и программирование у меня не профильным предметом было - на электронщика учился.

Я как раз осенью в одной своей самоделке в архитектурные вопросы уперся. Сходу красиво один важный кусок написать не получилось, а говнокод плодить не позволяет внутреннее эстетическое чувство. Три важные части сделал так что самому нравится,а с этой затык случился. Взял паузу до марта, размышляю как лучше средствами языка (Си,так как микроконтроллер) выразить основную творческую идею моего произведения :) И если не наделать «глупых» ошибок хорошо помогает компилятор и отладчик, то вот в архитектурных вопросах помочь может наверно только ИИ(и то совсем не факт),а у меня к нему доступа нет. Понятно что лучше бы с опытным мастером-программистом это пообсуждать,но у таких людей обычно лишнего свободного времени нет чтобы какого-то любителя из интернета всерьез консультировать. Это же не мелочь какая-то, которую можно парой фраз подсказать,тут пришлось бы тщательно вникать в проблему.

watchcat382
()

Предлагаю вот еще что обсудить: очевидно,что проекту на Си как минимум в трети случаев потребуется пользовательский интерфейс. Два других - библиотека и демон - пока отложим. И поищем средства для создания этого самого интерфейса. Например мне,как программисту-любителю, нравится вот эта библиотека:

http://xforms-toolkit.org/

Пользуюсь для своих поделок уже пару десятков лет. Может кто видел/знает что-нибудь еще столь же простое и удобное для самодельщиков? Чтобы именно из Си без плюсов можно было использовать.

watchcat382
()
Ответ на: комментарий от watchcat382

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

Ахаха что. GCC от версии к версии меняет поведение и всех его особенностей не знают двже авторы.

cumvillain
()
Ответ на: комментарий от watchcat382

Имеющиеся в сях грабли хотябы хорошо документированы и описаны в книгах и в интернете на каждом углу.

Да-да, «Memory violation».

И вероятность получить помощь по исправлению сишного кода выше в силу распространенности языка и его «носителей».

Это если вы пишете на современном С, не на С99.

Мало какой любитель (более-менее квалифицированный,не чайник) в одно лицо напишет программу такого размера чтобы «утонуть» своем коде и наделать совсем уж трудноуловимых ошибок в работе с памятью.

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

Мне тут давеча понадобилось Visual Studio крякнуть. Так вот, исправить готовый пример на сях с интернета - мне не удалось. Вечно какая-то ж..а с памятью. Сделал всё то же самое на C#. Во-первых, программа вышла всего в 20 строчек. На сях то же самое было как минимум вдвое длиннее. Во-вторых, сука, оно работает. Просто работает.

Т.е. лично для меня программирование на С - это прежде всего борьба с инструментом.

tiinn ★★★★★
()
Ответ на: комментарий от watchcat382

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

А что, со сбором, анализом и трассировкой требований у Вас всё хорошо, технологично и поддержано инструментально?

Архитектура-то из требований должна вытекать…

Shushundr ★★★
()
Ответ на: комментарий от watchcat382

А без разных видов строк нигде не обойтись.

Для (около)системного языка точно, что в С++ что в Rust их целая коллекция. В расте даже в стандартной библиотеке их три разных String, OsString, CString, плюс по ссылочной паре (типа &str) к каждой.

anonymous
()
Ответ на: комментарий от tiinn

И вероятность получить помощь по исправлению сишного кода выше в силу >>распространенности языка и его «носителей».

Это если вы пишете на современном С, не на С99.

В инстиутах изучается обычно достаточно классические диалект Си,поэтом как раз каких-нибудь более экзотических расширений типичные «носители языка» могут и не знать.

исправить готовый пример на сях с интернета - мне не удалось. Сделал всё то же самое на C#.

А для меня была бы в точности обратная ситуация - исправить пример на Си у меня есть,а на С# нет - потому что C# я просто вообще совсем не знаю.

watchcat382
()
Ответ на: комментарий от watchcat382

В инстиутах изучается обычно достаточно классические диалект Си,поэтом как раз каких-нибудь более экзотических расширений типичные «носители языка» могут и не знать.

Типичные «носители языка» - это вряд ли те, кто 20 лет назад изучали С в институте. Ну, либо, да, как на ЛОРе: изучал 20 лет назад в институте, с тех пор ничего не писал, но мнение имеет. Вот только пользы от него, как от козла молока.

tiinn ★★★★★
()
Ответ на: комментарий от anonymous

А без разных видов строк нигде не обойтись.

Для (около)системного языка точно, что в С++ что в Rust их целая >коллекция.

Поэтому я и не отношу классические «сишные» строки к недостатку Си. Не нравится - всегда можно воспользоваться какой-нибудь другой реализацией. Хотя конечно при обращении к чему-нибудь внешнему (протоколы связи, системные вызовы, специализированные библиотеки) всё равно придется заниматься конвертацией строк туда-сюда. На любом языке.

watchcat382
()
Ответ на: комментарий от watchcat382

Поэтому я и не отношу классические «сишные» строки к недостатку Си. Не нравится - всегда можно воспользоваться какой-нибудь другой реализацией.

Ага-ага. Опять же, приходит в Си человек, который всю жизнь писал на таких языках, где проблема со строками отсутствует как класс…

tiinn ★★★★★
()