Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить

Re: Вопросы по С/С++ (СИ)

Пт янв 28, 2022 13:36:34

Метод (или пр. код) для расчета a * b / c? Три переменные: uint32_t, цифры большие. Нет uint64_t и умножение > 32 бита, а если делится первым, теряю разрядность ниже. С float ОК (в первом приближении), но по нескольким причинам избегаю использовать.
Умножение в столбик в школе не учили? Вот и здесь можно умножить в столбик.
Деление тоже можно реализовать на циклических сдвигах вправо и вычитаниях. Примеры процедур можно найти в инете.
И разрядность можно сделать любую. Даже если компилятор такую не поддерживает.

Re: Вопросы по С/С++ (СИ)

Пт янв 28, 2022 17:54:17

Даже элементарный pipeline не сделать. Сваливаемся на процедурный код с объектного.

У людей постоянно какие-то непонятные хотелки, то исключения хотят на С++ для AVR, но поскольку они не тянут, то нужно писать не на С++ без исключений, а на С. Другой товарищ хочет писать на Java, тоже для AVR, а пишет в итоге не на С++ и даже не на С, а на ассме :) У меня исключений нет, динамического выделения памяти нет, виртуальная функций несколько на все либы, при этом какой фрагмент кода не возьми он весь привязан к фичам С++ и ощущения, что я сваливаюсь на процедурный код тоже почему-то не возникает.

ПростоНуб писал(а):Если же речь про параметр value, то в упор не понимаю, в чем тут разница между передачей указателя по значению в С и передачей ссылки в С++, которая в скомпилированном коде так же будет передаваться по значению адреса (того же значения указателя) в ней содержащегося.

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

ПростоНуб писал(а):Другое дело, что при жестких требованиях к производительности и памяти, не возникает никакого желания тащить такого монстра, как from_chars, себе в код. Например, зачем мне куча кода для парсинга чисел по основанию 36, если мне нужен парсинг только целых десятичных чисел? Как это не компилируй, но ворох лишнего кода всегда прибежит.

Во-первых, то что там много шаблонного кода(еще и проскакивают constexpr функции) еще не означает, что хоть какой-то код имеющий отношение к парсингу чисел по основанию 36 попадет в бинарник. Во-вторых, from_chars() не бросает исключения, динамически не выделяет память и не работает с локалью, так что в каком-то смысле она эмбедд ориентированная :) В-третьих, далеко не факт, что другие функции, в том числе сишные, лучше справятся с парсингом чисел с плавающей точкой... Наконец в данный момент сама функция не constexpr, а в следующем стандарте уже может таковой стать и тогда можно будет без проблем парсить любые числа хоть на 4-х битных мк. У меня в либе портов на этапе компиляции одной строкой сортируется массив структур по трем параметрам при помощи std::ranges::sort() и лямбды, а несколько лет назад использования такой тяжелой функции на мк казалось маловероятным.

ПростоНуб писал(а):Было бы смешно, если не было бы так грустно. Для примера, в MS SQL, PostgreSQL или Oracle подключить скомпилированное расширение в виде so/dll - элементарно, причем динамически без остановки сервиса. Потому что они написаны на C и ABI стандартизирован. А вот к Clickhouse - только с полной перекомпиляцией всего Clickhouse и рестартом сервиса, так как он написан на C++, а ABI в C++ меняется даже от версии к версии одного компилятора, не говоря уже о разных.
Тоже самое можно сказать и про ESP32, и про старшие МК на ARM, где расширения могут быть востребованы. а полная рекомпиляция или не желательна, или даже невозможна, так как все исходники недоступны.

О чем и речь, к мк все сказанное практически никакого отношения не имеет, тем более официально распространяемый gcc для ARM именуется не иначе как gcc-arm-none-eabi :)

ПростоНуб писал(а):Речь не о простоте для изучения (не думаю, что к C это относится, так же, как, для примера, к Lisp). А о простоте синтакиса.

Только не нужно Линуса приплетать, он сам на С++ не пишет и цитата относится к 2010 году, вероятно еще про С++03, по сути совершенно другой язык. А синтаксис у С то заметно проще, но это если брать языки в полном объеме, а если взять С и накатить поверх множество мелких улучшений из С++, то получится некое подмножество С++ с синтаксисом проще, чем у С. Последнее время мне даже попадалась парочка книг с подобным подходом, в одной из них автор называл такой С++ кажется Super C, а в D есть ключ компилятора отключающий часть возможностей и превращающий язык в Better C :)

Re: Вопросы по С/С++ (СИ)

Пт янв 28, 2022 20:14:18

У меня в проектах для микроконтроллеров отключены эксепшены, rtti и куча установлена в ноль. При этом кто-то мне запрещает использовать класы, шаблоны, auto, лямбды, constexpr, range-based for, вариативные шаблоны, концепты, перегрузку, вывод типов и т.д. и т.п. Да ну на! Эксепшенов им не хватает. То что есть сначала переварите.

Re: Вопросы по С/С++ (СИ)

Пт янв 28, 2022 20:37:56

Погодите еще вместе с непонятно почему запаздывающим gcc для ARM подъедут модули, которые уже работают в VS, хотя есть мелкие недочеты. И они настолько быстрее, что практически вся стандартная библиотека импортится одной
Код:
import core.std;

Более того в gcc 12 еще обещают новый на порядок более быстрый линкер...

Re: Вопросы по С/С++ (СИ)

Сб янв 29, 2022 11:44:52

У людей постоянно какие-то непонятные хотелки

Одна эта фраза говорит уже об очень многом...


Reflector писал(а):надежность и производительность будет под вопросом.

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

Reflector писал(а):Во-первых, то что там много шаблонного кода(еще и проскакивают constexpr функции) еще не означает, что хоть какой-то код имеющий отношение к парсингу чисел по основанию 36 попадет в бинарник.

А как он не попадет, если base будет переменная? Я могу ограничить пользователя, например, base<=10 при вводе, но у меня большие сомнения, что оптимизатор настолько умен, что не только увидит и запомнит это ограничение, но еще и применит его при оптимизации case в __to_chars_i()

Reflector писал(а):эта и множество других функций уже написаны профессионалами и доступны всем желающим

А ребята не знали. что профессионалы пишут только на С++ и их труды доступны всем желающим только на C++. А на остальных языках, включая C, профессионалы не пишут и труды не публикуются? )))

Reflector писал(а):В-третьих, далеко не факт, что другие функции, в том числе сишные, лучше справятся с парсингом чисел с плавающей точкой...

Вас несет. Возьмите и сравните c atof, как по размеру кода, так и по производительности, и уже после этого рассуждайте. А то уж очень демагогией попахивает. Если ничего не делать. то все будет "далеко не факт".

Reflector писал(а):
ПростоНуб писал(а):Было бы смешно, если не было бы так грустно. Для примера, в MS SQL, PostgreSQL или Oracle подключить скомпилированное расширение в виде so/dll - элементарно, причем динамически без остановки сервиса. Потому что они написаны на C и ABI стандартизирован. А вот к Clickhouse - только с полной перекомпиляцией всего Clickhouse и рестартом сервиса, так как он написан на C++, а ABI в C++ меняется даже от версии к версии одного компилятора, не говоря уже о разных.
Тоже самое можно сказать и про ESP32, и про старшие МК на ARM, где расширения могут быть востребованы. а полная рекомпиляция или не желательна, или даже невозможна, так как все исходники недоступны.

О чем и речь, к мк все сказанное практически никакого отношения не имеет

Для имеющих проблемы со зрением использовал полужирное начертание )))

Reflector писал(а):Только не нужно Линуса приплетать

Почему это не надо? Он достаточно четко выразился, что один и тот же код в C++ может, в зависимости от контекста, выполнять совершенно разные действия. Вы же сами это пропагандируете шаблонами. Вот только это очень удобно при написании программы, но сильно повышает трудоемкость при ее сопровождении, что как раз и подчеркнул Линус. Например, я сам не раз сталкивался с совершенно негуманоидой логикой реализации операций сложения или сравнения для некоторых объектов некоторыми программистами.

Добавлено after 10 minutes 29 seconds:
Эксепшенов им не хватает. То что есть сначала переварите.

Не бойтесь, давно переварили. Потому и нарвавшись один раз на необходимость чуть-ли не полностью переписывать код, переносимый с Linux на ESP32, сразу исчезает желание с C++ связываться. Так как C код портируется на порядок легче.

Re: Вопросы по С/С++ (СИ)

Сб янв 29, 2022 13:14:31

Не надо QT тащить в микроконтроллеры и с головой будет полный порядок. У меня проекты под микроконтроллеры на современном многоядерном компьютере/ноутбуке с SSD собираются в пределах 5-10 секунд. Простые даже засечь не успеваю.

Так как C код портируется на порядок легче.
Неправда. Код С++ намного проще и быстрее выводится на уровень абстракции объекта, когда не надо думать на каком процессоре или порту он будет работать, а можно просто реализовывать именно его данные и поведение.

ПростоНуб, переход на личности не делает ваши аргументы весомее, а скорее наоборот :(

Добавлено after 32 minutes 28 seconds:
А ребята не знали. что профессионалы пишут только на С++ и их труды доступны всем желающим только на C++. А на остальных языках, включая C, профессионалы не пишут и труды не публикуются? )))
Функции стандартной библиотеки имеют преимущества. Во-первых, их не надо искать по помойкам, они всегда под рукой. Во-вторых, они написаны в тесной связи с разработчиками компилятора. Многии из них реализует именно компилятор как встроенные функции. В-третьих, они в большинстве своём шаблонные. Это значит они инстанцируются наиболее подходящим способом, они хорошо инлайнятся, они хорошо оптимизируются. В-четвёртых, их действительно пишут профессионалы, что в случае с найденным на помойке кодом может оказаться далеко не так.

Re: Вопросы по С/С++ (СИ)

Сб янв 29, 2022 14:05:14

Правильно, не надо Qt, надо .Net ;)

Добавлено after 41 minute 20 seconds:
VladislavS, с чего Вы взяли, что .Net не по существу? Ну или огласите весь список, пожалуйста, чтоб Вас не нервировать.

Re: Вопросы по С/С++ (СИ)

Сб янв 29, 2022 16:18:52

ПростоНуб писал(а):Уже видно по исходникам, что рассматриваемая from_chars() сделана излишне универсальной и перегруженной.

Ок, можно ведь протестировать... Компилируем следующий код на F7:
Код:
PerfCounter perf;
perf.start();

static char arr[] = "1234567890";

volatile int val = atoi(arr);
   
auto t = perf.getElapsedTicks();
rtt.println(t, val);

Сама функция atoi, которая возвращает 0 при ошибке, потому непонятно как ей парсить "0", добавила к бинарнику 680 байт и исполнялась 309 тактов. Однако даже IDE рекомендует вместо atoi() использовать strtol(), которой ноль уже распарсить можно и для нее получаем +676 байт и 300 тактов. У меня есть собственная constexpr функция, с ней получается +128 байт и 182 такта. Наконец from_chars() показывает практически идентичный результат: +128 байт и 183 такта :)

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

Специально откопал старенький ноут, создаю в VisualGDB сишный проект на HAL мигающий светодиодом, по умолчанию он компилирует намного больше *.c файлов из HAL, чем нужно для светодиода, но тем не менее, полная пересборка с -O2 -flto занимает 8 сек. Теперь берем эмулятор спектрума на H750 который картину выводит одновременно на дисплей и VGA и где все начиная c пина и заканчивая либами USB/FMC/LTDC/SDMMC/FatFs в виде шаблонный классов и получаем 23 сек. Но зачем после каждого изменения полностью пересобирать проект, если что-то поменять в парочке файлов, то сама компиляция займет секунд 5 и еще 13 сек. линковка и время линковки можно существенно сократить отключив LTO. На нормально железе все будет происходить в разы быстрее и это даже без учета модулей...

ПростоНуб писал(а):А как он не попадет, если base будет переменная? Я могу ограничить пользователя, например, base<=10 при вводе, но у меня большие сомнения, что оптимизатор настолько умен, что не только увидит и запомнит это ограничение, но еще и применит его при оптимизации case в __to_chars_i()

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

ПростоНуб писал(а):Вас несет. Возьмите и сравните c atof, как по размеру кода, так и по производительности, и уже после этого рассуждайте. А то уж очень демагогией попахивает. Если ничего не делать. то все будет "далеко не факт".

Так сравнил уже, к сожалению поддержку float для from_chars() добавили только в gcc 11, которого для ARM еще нет, но я изначально ожидал возможный выигрыш именно на float, а оказалось он есть даже для целых чисел.

ПростоНуб писал(а):Для имеющих проблемы со зрением использовал полужирное начертание )))

Можно хоть все посты полужирным выделить и третий раз Линуса процитировать, все равно никто не перестанет писать на С++ для Cortex-M потому что возможны какие-то гипотетические проблемы с ABI на Cortex-A :) На ПК у меня никаких проблем с ABI нет, к С++ проектам линкуются либы от С, а C# грузит dll от C/C++, когда-то я даже портировал DirectX 9/10 на D, там с одной стороны либы в coff, а с другой в omf и ничего, большинство подобных проблем решаемо.

ПростоНуб писал(а):Почему это не надо? Он достаточно четко выразился, что один и тот же код в C++ может, в зависимости от контекста, выполнять совершенно разные действия. Вы же сами это пропагандируете шаблонами. Вот только это очень удобно при написании программы, но сильно повышает трудоемкость при ее сопровождении, что как раз и подчеркнул Линус. Например, я сам не раз сталкивался с совершенно негуманоидой логикой реализации операций сложения или сравнения для некоторых объектов некоторыми программистами.

Распространенный пример из мира эмбедда, пожалуйста. Лично у меня перегружены операторы для строгих перечислений, тут никаких вопросов быть не может, любой гайд по С++ будет рекомендовать не использовать сишные перечисления. Далее перегружен оператор "|" для пинов:
Код:
return sck | miso | mosi | nss;

Еще операторы сравнения для списка пинов и еще класс для работы с фиксированной точкой, там много чего перегружено, но в результате такой тип может работать там где и float:
Код:
constexpr auto f1 = sin(1.2345f);
constexpr auto f2 = sin(Fixed<12>(1.2345f));
rtt.println(f1, (float)f2);   // 0.94398332, 0.94397926

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

Re: Вопросы по С/С++ (СИ)

Сб янв 29, 2022 16:35:15

Перегрузка операторов для сложных типов как раз таки позволяет использовать их так же как простые, что повышает читаемость кода. Так то и название функций в С можно такими сделать, что запутаются сами K&R. Но мы же про программистов, а не обезьян, правда?

Re: Вопросы по С/С++ (СИ)

Вс янв 30, 2022 12:11:16

Вспомнил про еще одну полезную особенность ссылок. Если передавать по ссылке массив, то информация о его размере не теряется, в частности стандартная функция size() использует эту особенность:
Код:
template<typename T, std::size_t N>
constexpr std::size_t inline size(const T(&)[N]) { return N; }

int arr[10];
int arr2[size(arr)];

Re: Вопросы по С/С++ (СИ)

Вс фев 06, 2022 21:24:35

Знатоки стандарта, обязан ли первый кандидат всегда выигрывать перегрузку, если requires выполняется?
Код:
static inline void clear() requires requires() { base()->BRR; }
{
  base()->BRR = pin_mask;
}
static inline void clear()
{
  *((volatile uint16_t*)&base()->BSRR + 1) = pin_mask;
}

Re: Вопросы по С/С++ (СИ)

Вс фев 06, 2022 22:14:46

Да, для первой функции добавлено уточнение, а при перегрузке выбирается наиболее подходящий тип.

Re: Вопросы по С/С++ (СИ)

Вс фев 06, 2022 22:24:12

Смущает, что это не SFINAE, где специализация решает, а перегрузка. При перегрузке сигнатура решает или более короткий путь приведения к этой сигнатуре. Как на это requires влияет не очевидно.

Re: Вопросы по С/С++ (СИ)

Вс фев 06, 2022 22:50:59

Допустим у функции есть аргумент:
Код:
void foo(auto val) requires requires() { val.brr; } {}
void foo(auto val) {}

Можно написать отдельно концепт и получить функции с разными сигнатурами:
Код:
static void foo(HasBrr auto val) {}
static void foo(std::integral auto val) {}
static void foo(auto val) {}

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

Re: Вопросы по С/С++ (СИ)

Вс фев 06, 2022 22:57:26

С auto аргументом это шаблон, то есть, тут sfinae работает.

Re: Вопросы по С/С++ (СИ)

Вс фев 06, 2022 23:06:16

Концепты только с шаблонам и работают, не будет auto, значит функция должна находиться внутри шаблонного класса.
Код:
void foo() requires true {}   // Error: constraints on a non - templated function

А пример приведенный выше демонстрирует, что в принципе на requires можно смотреть как на часть сигнатуры, не важно есть у функции аргументы или нет.

ps. Вот еще пример подобных перегрузок без аргументов:
Спойлер
Код:
class Foo
{
public:
   void bar()& { rtt.println("foo&"); }
   void bar()const & { rtt.println("foo& const"); }
   void bar()&& { rtt.println("foo&&"); }
};

Foo foo;
foo.bar();      // "foo&"
   
constexpr Foo fooc;
fooc.bar();      // "foo& const"

Foo{}.bar();   // "foo&&" (временный объект)

Re: Вопросы по С/С++ (СИ)

Пн фев 07, 2022 00:48:16

А как думаешь, вот такое законно или хулиганство и в любой момент может "отвалиться"?
Код:
static inline void clear()
{
  if constexpr(requires(){ base()->BRR; })
    base()->BRR = pin_mask;
  else
    *((volatile uint16_t*)&base()->BSRR+1)=pin_mask;
}

Re: Вопросы по С/С++ (СИ)

Пн фев 07, 2022 01:20:36

Чего ему отваливаться, должно работать, главное чтобы base() возвращал не GPIO_TypeDef*, а T*, иначе если BRR в структуре не определен, то получим ошибку компиляция.

Re: Вопросы по С/С++ (СИ)

Пн фев 07, 2022 07:21:14

if constexpr "ленивая" - не вычисляет значение функций и не выводит их типы в провалившейся ветке. Пока base() возвращает auto, можно любую синтаксически верную хрень написать в невыполняющейся ветке. Если возвращать GPIO_TypeDef* конечно зафэйлится на BRR.

Re: Вопросы по С/С++ (СИ)

Пн фев 07, 2022 10:01:06

if constexpr "ленивая" - не вычисляет значение функций и не выводит их типы в провалившейся ветке.

Речь не про ветки, а про условие. Когда компилируется base(), то компилятор может определить возвращаемый тип даже при том, что он auto, соответственно при проверке должна быть ошибка. Но по факту ты прав, ошибки нет, получается сами функции возвращающие auto немного "ленивые".
Ответить