LINUX.ORG.RU

Вопросы по C, и вообще.

 , ,


2

7

Будем считать что я пишу прикладные программки.

  1. Как лучше обрабатывать malloc == NULL? Игнорировать или кидаться аbort() не хочется, но обработать нужно, обрабатывать каждый вызов?
  2. Писать свои строки или есть библиотека? Строки хранить как utf8 или utf32?
  3. Динамические массивы, писать свои, есть готовые? Как находить оптимальный размер для увеличение массива при расширении, нужно ли вообще заранее выделять память?
  4. Куда лучше выводить ошибку? Можно в консоль, но на винде не прокатит вроде, плюс ничего не видно.
  5. Нормальная ли идея: Есть много строк по 3-16 символов, сделать MyMemAllocate который при выделении (64 > X) байт, выделяет память в уже аллоцированном буфере на пару мегабайт к примеру... А при MyMemRealloc(X > 64) перемещает память из этого буфера в системную кучу. Перед данными хранить байт отвечающий за тип кучи.
  6. Когда структуру нужно передавать через стек а когда по указателю?
  7. на x86_64 быстрее uint32_t или uint64_t?
  8. for(...;i != len;...) vs for(...;i < len;...)
  9. Всегда ли ((unsigned)0-1) == ((unsigned)0-1)?
  10. На чем быстро рисовать графику (картиночки, кнопочки)? SDL2 говорят медленный.
  11. Есть много текста, с разным шрифтом, разным размером. Как лучше такое рисовать? (ttf), нарисовать алфавит для каждого {размер+шрифт}, или нарисовать алфавит с очень большим размером а потом сжимать для буков меньшего размера? Рендерит кто нибудь TTF на видеокарте кстати?
  12. Есть много объектов с одинаковыми и неизвестными именами, делать отдельную структуру (в виде чего?) где будут храниться эти имена дабы не занимать память одинаковыми строками?
  13. Как лучше хранить значения key:value что бы быстро с ними работать?
    1. если значений мало,
    2. если значений много.
  14. Можно ли как то поставить обработчик на изменение участка памяти? Костыль, но нужно. (Win/Linux хотя бы)
  15. Актуальна ли для современных систем фрагментация кучи?
  16. Какие библиотеки есть для многопоточного? Что можно почитать? SDL_Thread тоже медленный?
  17. Вот допустим решил я распарсить INI файл, как лучше его читать? По линиям? Сразу весь? Проецировать?
  18. Библиотека для RegExp?
  19. Какие флаги для строгости компилятора юзать стоит? Я использую: -std=c89 -Wall -pedantic

Ну или можно книжку где это расписанно.

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

2. Зачем писать свое, если все есть? Кодировка — КОИ8-Р, конечно!

3. Свои несложно написать. Всяко лучше говна из glib!

4. А при чем здесь мастдайка?

5. И охота тебе с буферами мучиться?

6. Структуру всегда нужно по указателю передавать.

7. Эквипенисуально.

8. Эквипенисуально.

9. Ты о чем? Если обе архитектуры одинаковый конец имеют, то да.

10. OpenGL.

11. Без понятия. Такой фигней не страдаю и тебе не советую. Вообще лучше держаться подальше от GUI.

12. Не въехал.

13. Хешируй. Даже если мало.

14. Разве что ты ведро пропатчишь.

15. Если активно пользуешь и большими кусками, вполне возможно.

16. pthreads самый кошерный, зачем обертки?

17. Сделай mmap и работай как с куском памяти. Есть куча библиотек. Я для себя взял одну и добавил преобразование в виде дерева для ускорения доступа. Еще можно было бы хэширование добавить, но влом.

18. Не пользуюсь этой гадостью и тебе не советую.

19. -std не надо, уже по умолчанию минимум 99, добавь еще -Wall -Werror. Ну и -Wno-trampolines для облегчения жизни.

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

2. А если я пишу для тех самых китайцев?
3. Ну удобнее то готовые взять.
4. На всякий.
5. Да вроде не особо напряжно.
9. Да в Rust ошибку выдает, я думал может быть непредсказумое переполнение.
11. Не выйдет, нужно GUI.
18. Нужно.
19. «уже по умолчанию минимум 99», мне нравится c89, плюс расширения GNU не везде есть.
Спасибо.

linuhs_user ()

Как всего многа...

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

Хотя ладно. Поотвечаю, где не согласен с аноном.

2. А ты подумай что тебе удобно. Единственный мой совет: хочешь широких символов, забудь о существовании wchar_t и юзай uint32_t или uint16_t. 16 бит и вовсе на все языки мира хватит. wchar_t непортируем.

4. В системный лог, когда это реально необходимо. В остальных случаях хватит stdout/stderr. Ну и логфайл, а то как собирать инфу с пользователей? Они тебе никогда не скажут полезной информации. Хотя может я не умею с ними общаться.

10. У SDL2 есть много разных бэкендов для рисования 2д графики. Но SDL2 это не гуй тулкит. Я бы вообще не писал гуй на Си, а то получится или уродство а-ля гтк, или инопланетное нечто как EFL, ну или просто сложно поддерживаемая копипаста.

11. Атласы и SDF(если есть возможность). Си тут ни при чём, алгоритм в принципе одинаков.

12. Не распарсил.

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

14. Посмотри в сорцы GDB. У него есть фича watchpoint. Работает кривенько и косо почти везде, но бывает полезным. В целом на такие вещи не стоит рассчитывать.

16. pthread для всего. Win32 треды для ущербных.

17. Сразу весь, потом разбирать.

18. PCRE.

19. Которые тебе нужны. Внимательно почитай доку к компилятору и подумай сам. Хотя можешь долбануть -Wall -Wextra -Wpedantic или -Weverything для Clang.

Советую побольше читать доков того, с чем ты работаешь.

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

не рассматривай

Это еще почему, а если мне нужен простенький GUI?

Используй раст

И с помощью чего там рисовать? Как там с рисовкой TTF? Откину все мои остальные проблемы.

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

Ты может сначала попробуешь писать, а потом задавать вопросы?

У меня все в пк отвалилось, игры не запускаются, двачи унылы, я пишу 24/7.

2. uint16_t

Это худший вариант, он не всегда вмещает символ полностью, при этом много ест.

10.

Софтваре и акселерейтед (dx, opengl, vulcan). Nuklear хороший.
Понятно, спасибо.

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

Это худший вариант, он не всегда вмещает символ полностью, при этом много ест.

Какой символ численно больше 0xFFFF тебе хоть раз пригодился? Вот только честно, без всяких там смайликов для п***ров, эмоджи их вроде зовут. Много ест? Всего в джва раза больше.

Мне вообще по нраву больше мультибайт. По нему итерировать несложно, пакуется наиболее оптимально, однако для того, чтобы вытащить N-ый символ, тебе придётся сначала проверить все предыдущие. Всё зависит от задачи, мне так не приходится вытаскивать символ. :)

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

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

Ты сначала попробуй, а потом думай, что ДЛЯ ТЕБЯ будет удобно. С первого раза всё равно не сделаешь ведь идеально, не так ли?

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

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

linuhs_user ()

1. лучше уж abort(), чем полный игнор обработки. 2. не можешь работать с сишными строками - бери c++ 3. бери c++ 4. главное чтоб выводилось через какую-то одну функцию, куда - потом придумаешь. 5. преждевременная оптимизация 6. когда нужна копия структуры - по значению, во всех остальных случаях - по указателю 7. тесты рулят 8. второй вариант, он более устойчив к ошибкам 9. UB 10. кому медленный? тесты конкретно твоего случая рулят. а то на заборе тоже написано. 11. векторные шрифты. 12. c++, sharep_ptr 13. std::map 16. pthreads, а вообще - смотри по ситуации, в qt под капотом может быть что-то своё. 17. парсить - построчно, читать - как угодно. 18. смотря сколько тебе от него надо. можно и posix regex обойтись, который есть в libc, не хватит - pcre. 19. -std=c99 -Wall -Wextra -pedantic -Wformat -Wformat-security -Werror=format-security [-fstack-protector --param ssp-buffer-size=4]

anonymous ()

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

xpahos ★★★★★ ()

7. проц может сложить два 64 битных числа или две пары 32 битных за одинаковое время, следовательно в некоторых случаях uint32_t будет немного быстрее. Однако если ты будешь запускать код на OpenBSD то на фоне тормозов стандартной библиотеки, ты этого не заметишь)

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

1. В реале такая ситуация означает, что можно комп вырубать.

Или просто исчерпан лимит на виртуальную память (ulimit -v).

Но лучше для совместимости проверять.

Точно нужно проверять.

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

2. Это твои половые трудности

9. если тебе нужен педеrust, иди в гей-клуб вопросы задавай

11. делай веб-морду. Я серьезно.

19. в жопу системы, где нет гнутых расширений!!!

anonymous ()

for(...;i != len;...) vs for(...;i < len;...)

Зависит от того, как у тебя меняется i. В первом случае допускается, что i может стать больше len, проскочив значение i = len, и цикл станет бесконечным.

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

Это худший вариант, он не всегда вмещает символ полностью, при этом много ест.

И uint32_t не всегда вместит символ полностью, и если затачиваться на обработку уникода - тебе всё равно путь к какой-нибудь либе, а если сам всё будешь делать, то большой разницы, ИМХО, не будет, что ты будешь обрабатывать - двубайтные или четырёхбайтные «символы».

yyk ★★★★★ ()

6. Если тебе нужная копия, то через стек, иначе через указатель.

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

unC0Rr ★★★★★ ()

Как лучше обрабатывать malloc == NULL? Игнорировать или кидаться аbort() не хочется, но обработать нужно, обрабатывать каждый вызов?

Да, конечно, обрабатывать каждый вызов. Это же не C++, где можно выбросить std::bad_alloc из любого места и поймать его в нужном.

Писать свои строки или есть библиотека?

Стандартной библиотеки, естественно, нет, если не считать string.h.

Строки хранить как utf8 или utf32?

Либо UTF-8, либо wchar_t.

Динамические массивы, писать свои, есть готовые?

Стандартных, естественно, нет. Тащите библиотеку (посмотрите на Apache Portable Runtime, там много вкусностей) или пишите свои.

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

Считается, что в 3/2 раза увеличивать «нормально», но полноценный ответ Вам даст только профайлинг именно Ваших паттернов использование памяти.

Куда лучше выводить ошибку? Можно в консоль, но на винде не прокатит вроде, плюс ничего не видно.

Отделите платформо-зависимый слой с интерфейсом пользователя от программной логики. Программная логика пусть выдаёт enum или (в крайнем случае) char* с сообщением об ошибке, а платформоспецифичный интерфейс дёргает MessageBox / puts / IupMessageError (да, посмотрите IUP, прекрасная кроссплатформенная библиотека рисования интерфейсов на C89).

Нормальная ли идея: Есть много строк по 3-16 символов, сделать MyMemAllocate который при выделении (64 > X) байт, выделяет память в уже аллоцированном буфере на пару мегабайт к примеру... А при MyMemRealloc(X > 64) перемещает память из этого буфера в системную кучу. Перед данными хранить байт отвечающий за тип кучи.

Premature optimization is the root of all evil.

Когда структуру нужно передавать через стек а когда по указателю?

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

на x86_64 быстрее uint32_t или uint64_t?

Нет, uint_fast32_t.

anonymous ()

for(...;i != len;...) vs for(...;i < len;...)

Не важно. i < len более defensive (а ВДРУГ кто-то изменит i внутри цикла, и тот превысит len?), но это вопрос стиля.

Всегда ли ((unsigned)0-1) == ((unsigned)0-1)?

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

На чем быстро рисовать графику (картиночки, кнопочки)? SDL2 говорят медленный.

Кнопочки? Быстро в каком смысле, для программиста (IUP!) или для компьютера?

Есть много текста, с разным шрифтом, разным размером. Как лучше такое рисовать? (ttf), нарисовать алфавит для каждого {размер+шрифт}, или нарисовать алфавит с очень большим размером а потом сжимать для буков меньшего размера? Рендерит кто нибудь TTF на видеокарте кстати?

Не мучайтесь, возьмите библиотеку, которая сама рендерит rich text. Заодно предотвратите кучу уязвимостей и corner cases в своём парсере.

Есть много объектов с одинаковыми и неизвестными именами, делать отдельную структуру (в виде чего?) где будут храниться эти имена дабы не занимать память одинаковыми строками?

Имена что, мегабайты весят? Много - это сколько, миллиарды?

Как лучше хранить значения key:value что бы быстро с ними работать?
если значений много.

uthash.

если значений мало,

Ну, может быть, дерево.

Почитайте Кормэна, прежде чем задавать такие вопросы.

Можно ли как то поставить обработчик на изменение участка памяти? Костыль, но нужно. (Win/Linux хотя бы)

Зачем?

Актуальна ли для современных систем фрагментация кучи?

Premature optimization... Но да, актуальна.

Какие библиотеки есть для многопоточного? Что можно почитать? SDL_Thread тоже медленный?

pthreads. std::thread, если всё-таки передумаете. Почитайте Бутенхофа Programming with POSIX threads.

Вот допустим решил я распарсить INI файл, как лучше его читать? По линиям? Сразу весь? Проецировать?

Возьмите библиотеку. https://github.com/ndevilla/iniparser тот же.

Библиотека для RegExp?

libpcre, конечно же.

Какие флаги для строгости компилятора юзать стоит? Я использую: -std=c89 -Wall -pedantic

Можете взять -Wextra -fsanitize=undefined -fsanitize=address, если хотите почувствовать себя маньяком.

P.S. Учтите, что stdint.h НЕТ в C89.

anonymous ()

отвечу на некоторые вопросы

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

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

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

4. в маздае не знаю. в лине любой админ тебе скажет, что в syslog. но если это юзерская софтина, можно и в консоль.

5. зачем такие сложности? я не понимаю, что ты таким образом хочешь сэкономить.

6. лучше всегда по указателю. но если структура будет удалена после передачи в функцию или может быть изменена, пока функция не завершилась - тогда, естественно, по значению. зависит от того, как собираешься её использовать.

7. одинаково. но в 64 бита можно упихать 2 по 32. хотя это не создаст тебе измеримого на практике ускорения в 99.99% случаев.

8. зависит от знаковости и от конкретной ситуации. "!=" не есть конкретно больше или меньше.

9. всегда. ну, в пределах одной машины.

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

13. если мало - map, если много - хэш. вид хэширования зависит от того, насколько часто приходится добавлять элементы (некоторые хэши шустрее, но не равномерно распределены и могут вызывать коллизии).

14. в дебаге - да. на практике, теоретически, можно (через дебаг). но в общем случае сложно. в частных вариантах можно попробовать через самописные аллокаторы.

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

16. многопоточность - системная функция. вряд ли есть что-то быстрее обычных системных API. к тому же, они примитивны и не вызывают проблем.

17. если твой ini-файл меньше гигабайта, проецировать нет смысла :) читать пофигу как. опять же, если он невелик.

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

19. зависит от твоих целей. но -Wall всяко полезен.

Iron_Bug ★★★ ()
Последнее исправление: Iron_Bug (всего исправлений: 1)

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

man setrlimit

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

Лучше отдамся Borrow Checker'у в туалете гей клуба.

Ты сначала попади в гей-клуб, меня с друзьями как-то не пустили в Москве в гей-клуб, сказали, что по нам видно, что мы «не такие».

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

либо wchar_t

Why?

Стандартной библиотеки, естественно, нет

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

да, посмотрите IUP

Отличная вещица. Глянул немного.

uint_fast32_t

Точно! Забыл уже.

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

Кнопочки? Быстро в каком смысле, для программиста (IUP!) или для компьютера?

Для компьютера приоритетнее.

Не мучайтесь, возьмите библиотеку, которая сама рендерит rich text

Да мне не так много и писать, я по максимуму готовое беру.

P.S. Учтите, что stdint.h НЕТ в C89.

Его всегда можно добавить) Да и в SDL2 есть.

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

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

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

и общаться с софтиной через сигналы или шареную память.

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

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

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

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

Простенький - это какой? Убогий? Вы в курсе о hidpi, hig и нативной отрисовке шрифтов? Нет? Тогда используйте Qt и не мучайте людей.

Разве что ваша прога делается исключительно для любителей openbsd с crt мониторами, которые застряли в 90-х.

RazrFalcon ★★★★★ ()