LINUX.ORG.RU

понять Си

 , ,


3

2

посоветуйте, что почитать для поверхностного понимания философии языка Си.
я вот экспериментирую (Си+ООП из C++), решил сделать банальную функцию, возвращающую строку с датой:

char* sh_time::getTimeString() {
  time_t t = time(0);
  struct tm * now = localtime( & t );
  //(*s) << printf("%d-%02d-%02d\n", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday);
  size_t sz;
  sz = snprintf(NULL, 0, "%d-%02d-%02d\n", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday);
  s = (char *)malloc(sz + 1);
  snprintf(s, sz+1, "%d-%02d-%02d\n", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday);
  return(s);
}

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

★★★

Последнее исправление: CYB3R (всего исправлений: 4)

посоветуйте, что почитать для поверхностного понимания философии языка Си.

Ассемблер.

Я серьёзно, между прочим. Си - это кроссплатформенный ассемблер. Ждать от него большего не стоит.

или же для подобных задач есть стандартизированные пути решения? (я не про готовые функции, а про традиционные способы решения задач)

Используй готовые библиотеки или пиши их сам. Это и есть «обычные пути решения» согласно предназначению языка. Есть куча библиотек для работы со строками, каждая со своими преимуществами и недостатками. Например: http://www.and.org/vstr/comparison

каждый на ровном месте огород городит

Используй glib. Вот например функция, которая тебе нужна: https://developer.gnome.org/glib/2.30/glib-String-Utility-Functions.html#g-st...

anonymous
()

Не обратил внимания, что у ТСа «Си с классами».

Это тяжелые вещества, завязывай. Либо пиши на нормальном Си, либо используй возможности Си++ на полную катушку. А это, извините, бред.

anonymous
()

Си+ООП из C++

Ааа, как бы это помягче, скажи ка, а где ты про это прочитал? Я бы тоже почитал, чисто поржать.

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

Не обратил внимания, что у ТСа «Си с классами».

я предупредил даже.

Либо пиши на нормальном Си,

там нет классов.

либо используй возможности Си++ на полную катушку.

не дорос ещё.
streams так и вообще бесят, эзотерика какая-то.

А это, извините, бред.

писать так - возможно.
тренироваться - ничуть.

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

скажи ка, а где ты про это прочитал?

я посмотрел на си, посмотрел на плюсы, решил, что мне нужно ООП, но не нужна бредятина, как те же streams.

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

Кстати, никогда не понимал людей, которые читают «учебники» языка.

Единственный документ, который требуется прочитать, находится тут: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf

Если конечно голова на плечах есть. Если нету, учебники всё равно не помогут.

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

loool зачем тебе вообще ооп? питон^Wпхп как раз для тебя, я серьёзно.

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

там нет классов.

Там «классы» пишутся самостоятельно. Смотри как сделано в gobject, например. Да, получается длинее. Зато и возможностей больше.

не дорос ещё. streams так и вообще бесят, эзотерика какая-то.

В общем-то, я лет 10 назад находится в таком же положении. С одной стороны, стандартная библиотека крестов - это треш и угар (особенно в те времена была таковой, когда каждый компилятор изгалялся по-своему), с другой - хочется автоматического вызова деструкторов и обработки исключений. Писал на «Си++ без шаблонов и без libstd++».

А потом я дорос. Только не до использования Си++, а до понимания, что чистого Си для моих задач полностью достаточно. Там, а где не хватает Си, есть языки типа питона.

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

я посмотрел на си, посмотрел на плюсы, решил, что мне нужно ООП, но не нужна бредятина, как те же streams.

Посмотри на Objective-C.

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

слышал про такое, но на статье в википедии куча упоминаний apple, поэтому решил не трогать.

batekman ★★★
() автор топика

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

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

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

Охохо. Костыли-костылики.

ТС, не слушай его.

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

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

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

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

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

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

Ты и C не знаешь.

потому и создал тред - хочу понять, чего от него ждать.

man strftime

это как первокласснику давать калькулятор вместо кнута, пряника и таблицы умножения.
сказал же - экспериментирую.

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

Не костылики, а разделение ответственности. Ф-я не в курсе про тип аллокатора, как ты заметил

Ага. Разделение ответственности в виде дефайнов в заголовочном файле. Очень архитектурно правильное и, главное, гибкое решение. Да, я стебусь.

а передавать его чтобы он сам выделял это и есть маразм.

Доказать сможешь? Полагаю, что нет.

Напиши выделятор, который выделит на стеке вызывающего, ради прикола.

Сунь два пальца в розетку ради прикола.

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

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

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

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

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

Ты и C не знаешь.

потому и создал тред - хочу понять, чего от него ждать.

Ну и жирнота! Ты типа знал С++ и не знаешь С? Гнать тебя ссаными тряпками!

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

Просто не суй одновременно два пальца, и будь осторожен.

Следи за собой.

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

Доказать сможешь? Полагаю, что нет.

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

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

сказал же - экспериментирую.

Это велосипед. Если ты так экспериментируешь с каждым примитивом, то я представляю как выглядит твой код.

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

там нет классов.

В вашем любимом линуксе внутре наверняка одни классы, особенно в драйверах

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

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

Не понял. В крестах вызываются деструкторы локальных объектов при выходе из скопа любым способом. Или ты хочешь логику try-finally? В принципе, можно навелосипедить при помощи анонимной функции, завёрнутой в локальный объект...

void f() { finally fin([&]() { logger << «leaving f()!»; }); }

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

там нет классов.

Там есть структуры

streams так и вообще бесят, эзотерика какая-то.

Все понятно. Вброс слишком жирный. Я за бан.

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

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

Этот маразм иногда бывает нужен.

Есть даже мнение, что разделение логики аллокации (как и любого взаимодействия со средой) от алгоритма - Хорошая Идея. А вот впердоливание констант времени компиляции где попало - очень плохая.

Всё зависит от конкретной ситуации. Скажем, все кресты разом - это один большой архитектурный маразм. Тем не менее, писать высокопроизводительный графический движок я бы ни на Си, ни на managed языках не взялся. Тут кресты - единственный вариант.

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

Нет, я про то, что у структуры возможен явный деструктор, который не только обнулит поинтеры, но и выполнит завершающие деаллоки, а у скопа — не возможен. Поэтому нельзя без костылей выйти так, чтобы char *tmp не утек.

А в структуре ты пишешь в деструкторе free(tmp) и не паришься.

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

Ну и хрена тогда это сраное ООП пытаешься куда-то сунуть? Выучи С, тогда поймешь, что ООП — говно.

Eddy_Em ☆☆☆☆☆
()

Если ctime(3) не нравится, то можно как-то так

std::string format_time() {
    time_t t = time(0);
    tm *lt = localtime(&t);
    const size_t sz = 10 + 1;
    char s[sz];
    strftime(s, sz, "%F", lt);
    return s;
}

всякие malloc и free тут не нужны.

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

там нет классов.

А зачем тебе классы в C?

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

Потому что сконцентрированное управление ресурсами рулит, и поэтому кресты так привлекательны, и даже были бы вином, если бы не религиозные фанатики. Я в целом с тобой согласен, просто представляю публике другой конец палки, только и всего.

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

Нет, я про то, что у структуры возможен явный деструктор, который не только обнулит поинтеры, но и выполнит завершающие деаллоки, а у скопа — не возможен. Поэтому нельзя без костылей выйти так, чтобы char *tmp не утек.

Ну это и есть то, что называется finally-блок (в тех ЯП, которые его умеют). Как я и сказал, можно проэмулировать в новой версии крестов при помощи замыкания, завёрнутого в локальный объект.

А вот в Си хотелось бы такую фишку, да.

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

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

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

Да и в крестах многим хотелось бы, если бы они понимали, что вся идеология вертится вокруг этой концептуальной недоделки. С точки зрения управления ресурсами, std::string не более чем костыльный прокси, который освобождает char *tmp, сам будучи расположенным непосредственно в скопе. И все из-за отличия скопа от структуры. Трай финали это оно, но опять же костыль, который будет по-любому осужден фанатиками и не принят в бест практисес.

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

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

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

А финали вызывается при ретурне из трая?

«В сферическом в вакууме нормальном языке» - при любом выходе из блока: по return, break из цикла, goto за пределы скопа, раскрутка стека по броску исключения и т.п.

В общем-то, как раз такие гарантии вызова у деструкторов в крестах. Что и позволяет эмулировать finally через специальный костыль.

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

Ну тут разница именно что «языковая». Дестуктор и finally-блок - суть одно и то же, просто расположены на разных уровнях композиции: структурном и процедурном.

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

Трай финали это оно, но опять же костыль, который будет по-любому осужден фанатиками и не принят в бест практисес.

Вот по поводу фанатиков. Важно понимать, что кресты - это такой «специальный хаскель для Си». Если рассматривать его как язык типа Java, то получается сплошная нецензурщина и толпы быдлокодеров. Которым, в отличие от java, компилятор еще и не даёт по рукам.

Имхо, пусть к успешному использованию крестов:

* Несколько лет писать на Си, хорошо осознать возможности и ограничения языка. Захотеть большего контроля над кодом в compile-time.

* Познакомиться с хаскелем, понять, какие полезные концепции в нём есть. Осознать, что хаскель сам по себе не пригоден для практического применения.

* Начать писать на крестах, используя опыт из первого пункта и концепции из второго.

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

впердоливание констант времени компиляции где попало - очень плохая.

Не где попало, а в связанном месте. Меняя функцию, меняешь связанный дефайн. Не нравятся дефайны, экспортируй константу. Это и есть компайл-тайм инкапсуляция без потери абстракции аллокатора.

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

Познакомиться с хаскелем, понять, какие полезные концепции в нём есть.

В принципе, согласен. Только на хаскеле свет клином не сошёлся. Можно из многих языков что-то полезное утянуть в плюсы.

const86 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.