Как стать автором
Обновить

Комментарии 34

про управление форматированием в C странный заход. Там все есть, что надо.

НЛО прилетело и опубликовало эту надпись здесь

А как их не использовать совместно? Распространенный lvgl написан на C, gtk - снова C, и так куда не плюнь - везде пересечения...

Прошу не серчать, я не програмист, я конструктор, но сообщество ИТ специфично и интересно (да, это как отдушина).

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

- В С++ решение выделить память С ВЫРАВНИВАЕМ и последующим удалением мягко скажем многословней чем в СИ.
- Само выделение очень вариативно и по синтаксису и по способам, это сбивает с толку новичка
- Даже выделив её покапаться изрядно в ней (перемещения, наложения и пр.) средствами C++ используя только его и std:: порождает ощущение танцев очень похожих на Си, но с прелюдией.


Да, есть обёртки над СИшными операциями с блоками памяти, но я не увидел какого то нового уровня обеспечения безопасности при большей многословности кода.

Буду признателен:
Лаконичному примеру в C++ который алоцирует с выравниванием память и совершает например запись люб. значения по люб. по адресу и в добавок выполняет аналог memmove с наложением. Но сугубо в рамках C++ и std::

Спасибо!

 А почему в C++ выделить память сложнее с выравниванием? Есть же T *PTR = new (std::align_val_t(ALIGN)) T[ARRAY_SIZE] (для удаления delete[] (std::align_val_t(ALIGN), PTR), также есть версия без []) или std::aligned_alloc (для удаления std::free). Более того, вы просили пример, вот он: https://pastebin.com/TPHftGiA (да, я использовал rand(), который типа C, -- но это просто для заполнения массива, то, что вы просили, сделано средствами C++).

Действительно, похоже на код в стиле C++, однако я не очень понимаю, чем тот же оператор new так сильно отличается от вызова malloc из std библиотеки C. Хотя отличия несомненно есть, это не вносит существенной разницы. В частности, в вашем примере оператор new - это функция malloc, сказанная другими словами. Да и в случае перевыделения памяти в C++ всё равно неизбежно приходится использовать realloc. А, простите, из-за того, что всю стандартную библиотеку языка C поставили под неймспейс std, считать код подогнанным под идеологию C++, ну, лично для меня, не очень корректно.

Можете уточнить что значит бинарное хранение конфиг файлов и почему нужно именно выравнивание?

что значит бинарное хранение конфиг файлов

берем структуру, и пишем ее как есть в файл/eeprom. Обычно актуально для маленьких микроконтроллеров, где сериализация будет дорогой штукой по ресурсам. Ну а чтобы это занимало минимум места, выравниваем побайтово.

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

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

struct __attribute__((packed)) Foo {
    char a;
    int c;
    char b;
};

спасибо, просто мне надо было уточнить о чем речь + я попутно посмотрел хотябы на своём коде cache-misses в моём коде (без контроллеров с задержкой 60 мс программа даёт 39процентов, если выключить задержку вообще 1 процент, ) .

насчет примера тоже спасибо. приложу свой пример (пример к тому что файл это набор char) там не возьмусь прям советовать как лучше

unordered_map<string,vector<pair<int,vector<uint8_t>>>> worker;
...
  void serialize()
  {
    ofstream file;
    file.open("assets.bin",ios::binary);
    int s=worker.size();
    //cout << s <<" 1"<< endl;
    file.seekp(0);
    file.write(reinterpret_cast<const char*>(&s),sizeof(s));
    for(auto a:worker)
      {
	const char* b=a.first.data();
	int slen=a.first.size();
	int n1=a.second.size();
	file.write(reinterpret_cast<const char*>(b),sizeof(char)*40);
	file.write(reinterpret_cast<char*>(&n1),sizeof(n1));
	//cout << b <<" 3"<< endl;
	std::vector<std::pair<int,vector<uint8_t>>> l=a.second;
	for(auto& c:l)
	  {
	    int k=c.first;
	    vector<uint8_t>t=c.second;
	    //cout << k <<" 2"<< endl;
	    file.write(reinterpret_cast<const char*>(&k),sizeof(k));
	    writeVector(file,t);
	  }
      }
    file.close();
  }
//сразу файлами тоесть на входе факторка дающая указатели 
//или загрузил все файлы и через факторку дал указатели, 
//где в программе удалил и по новой единственный нюанс не знаю 
//как на контроллерах на андроид как я понял надо кинуть в JNI ifstream
//я заюзал SDL3 уже перегруженое чтение

Язык C достаточно простой и эффективный. На нем можно писать простые функции и эффективные решения. На нем много библиотек. Если вы делаете ошибки в C - рано увеличивать сложность и переходить к C++. И совет не используйте выделение памяти в стиле С в C++ потому что можно выделить что-то в стеке... Это очень странно.

Каша какая-то. Нет ничего плохого в использовании готового C кода в плюсах. А вот за что надо руки отбивать - за программирование в сишном стиле на плюсах. Ну и как-то по детски написано. Что ж будет, когда автор откроет для себя stdcall и cdecl)

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

А знаете, что ещё безопаснее, чем Си? Rust /s

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

На мой взгляд, уместнее было бы рассказать о разнице в приведении типов (как например здесь) или о поведении C-cast в C++ коде.

На правах оффтопа: вы же игровой движок разрабатываете, было бы гораздо интереснее прочитать от вас кейсы по этой теме причем любой. Например, как 3D редактор в него интегрировали. Гайджины и Playrix в своих блогах раньше хорошие статьи размещали по теме.

На правах шутки:

Тут один известный в геймдеве мужик в очках рассказывает, как он пишет на C++ сейчас (см. с отметки 1:55)

cin и cout весьма медленные по сравнению с scanf и printf. Так что если нужно выжимать производительность, то совет из статьи так себе.

Если правильно использовать (std::ios::sync_with_stdio(false); std::cin.tie(nullptr); и не пользоваться std::endl (он сбрасывает буффер вывода, вместо него лучше использовать '\n' -- это не сбрасывает буффер вывода), то std::cin и std::cout будут быстрее. Другое дело, что в Microsoft Visual C++ не поддерживается std::ios::sync_with_stdio(false); (ну как бы такая функция есть, но она ничего не делает, т. е. std::cin и std::cout не ускоряются от нее)... Но даже так в C++ стандартный ввод-вывод все еще остается достаточно медленным.

Хмм, у меня и на Clang со всеми этими ухищрениями было медленнее. Надо перепроверить на 20-м.

По крайней мере, то, что я сказал, для g++ будет верно. В clang походу также, как и в Microsoft Visual C++ не поддерживается std::ios::sync_with_stdio(false); (ну как бы такая функция есть, но она ничего не делает, т. е. std::cin и std::cout не ускоряются от нее): 1, 2.

Нужно просто использовать std::print ;)

НЛО прилетело и опубликовало эту надпись здесь

Автор статьи скорее расписался в недостаточной квалификации нежели привел доводы.

С и С++ хоть и похожи, но это инструменты для разных задач. Это как раньше писали код на С и делали ассемблерных вставки для ускорения задач. Так и сейчас в С++ вставки на С для ускорения кода и возможности работы напрямую с памятью без API прокладок. Я уже молчу что код на С без проблем переносится от версии к версии компилятора.

Какие вставки на C вы делаете для ускорения задач?

На текущий момент язык C - это в первую очередь ABI склеивающий разные языки. Если смотреть на него с такой точки зрения то это действительно разные задачи с C++.

В своё время именно незабвенное творение Дохлогострауса и стандартной библиотеки С достало меня настолько, что я поменял карьеру и ушёл из разработки насовсем в QA автоматизацию на Python. Я пришёл к выводу, что за все годы кодинга на С/С++ я не написал ничего значительного, а какие то отдельные куски кода в каких то подсистемах, чаще всего которые даже протестировать то нормально было невозможно. Ну юнит тест, да: слёзы одни. Просто фрагментарные куски в огромной системе. Да, я фиговый разработчик и мне не особенно нравится писать код по требованиям, но даже с учётом этого С/С++ никогда не давал мне ощущения законченности и не приносил удовлетворения (не говоря о куче ошибок, которые находили потом QA). Да, на СС++ написаны драйвера и операционные системы и прочий рокет сайенс, но это просто не мой уровень.

Ну видимо тебе плевать, когда прога, которая должна жрать 300 КБ жрет 10 МБ и т.д.

Я вот от такого не имею никакой удовлетворенности...

Каждому овощу - свой фрукт :)

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

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

НЛО прилетело и опубликовало эту надпись здесь

А чего тут странного? Необработанный массив сосны, например, или дуба, ходовой товар, кстати. Если, повезет, то и ясеня, но чаще все-таки дуба.

НЛО прилетело и опубликовало эту надпись здесь

вредит чистоте и безопасности кода.

Как обычно, "старая песня" для криворуких, на какую я как-то ложил.

Продолжу использовать c в c++ и дальше, там где мне нравится.

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

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации