Перейти к содержанию
    

Стили оформления программ на C/C++ и их применимость

Для ембеда ещё до кучи consteval для функций, тоже, насколько помню, в C++20 ввели.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 минут назад, dxp сказал:

consteval для функций

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, VladislavS сказал:

Есть другой инструмент не пустить код в рантайм.

Что имеется в виду?

1 час назад, VladislavS сказал:

Не вижу особого смысла ограничивать функции этапом компиляции. Если они шаблонные, то это автоматом получится

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

57 минут назад, dxp сказал:

Почему с шаблонными это автоматом получится?

Согласен, тут некорректно сформулировал. 

57 минут назад, dxp сказал:

Что имеется в виду?

Если речь про обычное программирование, то на С++17 гарантия выполнения код в компайлтайме - использовать значение функции там где должна быть константа. Например, constexpr auto var = f();  , в if constexpr, как параметр шаблона. Иногда вместо consteval действительно приходится промежуточную constexpr "переменную" делать. С другой стороны, при максимальной оптимизации компилятор и так всё это делает. Уговаривать его надо когда нет оптимизации, а у меня такого не бывает.

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 1/5/2024 at 8:59 AM, dxp said:

3. range-based циклы. Два примера:

int buf[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
int sum   = 0;

// example 1
for(size_t i = 0; i < sizeof(buf)/sizeof(buf[0]); ++i)
{
    sum += buf[i];
}
            
// example 2
for(auto &i : buf)
{
    sum += i;
}

Какой вариант короче, проще писать и читать?

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

 

On 1/5/2024 at 8:59 AM, dxp said:

7. Лямбда-выражения. 

Это вообще вывих мозга и мартышкин язык на подобии регулярных выражений.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

24 минуты назад, dimka76 сказал:

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

Это вот эта фигня 

sizeof(buf)/sizeof(buf[0]

более читабельная? 🙂

Он просто вам более привычен, только и всего. В Python циклы от рождения выглядят:

for i in seq:
   ...

всем нравится: простая запись итерации по последовательности. Все эти

size_t int = 0, ++i, buf[i]

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

Вот тут просто вместо in используется двоеточие:

for(int x : buf)
{
    ...

Запись по стилю очень близка, а по семантике так вообще то же самое. 

И в отличие от традиционного варианта тут, как и в Python, не нужно менять форму записи при изменении типа последовательности: массив, вектор, строка, список.

Попробуйте, вам понравится. 🙂 Сегодня уже трудно найти компилятор, который бы не поддерживал C++11.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 1/5/2024 at 2:25 PM, dxp said:

В Python циклы 

......

.....

как и в Python

А зачем вы сравниваете с Python ?

Речь ведь идет про Си и С++.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

40 минут назад, dimka76 сказал:

Это вообще вывих мозга и мартышкин язык на подобии регулярных выражений.

[]{...}   // кратко, если агрументы не нужны
[](){...} // полная запись

Где вывих мозга? Вместо имени функции используются квадратные скобки и всё. Это выражение можно присвоить переменной -- это будет имя объекта класса-функтора. И передавать это имя (объект класса) везде, где ожидается функция. Попутно можно это выражение написать прямо сразу по месту, что очень удобно. Когда видите такую запись, просто представляйте себе объект класса функтора -- класс, в котором одна-единственная функция-член operator(), которая и вызывается в точке, где ожидается функция.

15 минут назад, dimka76 сказал:

А зачем вы сравниваете с Python ?

Речь ведь идет про Си и С++.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

48 минут назад, dxp сказал:

это низкоуровневая запись,

Самое прикольное, что это не имеет ничего общего с конечным кодом. Компилятор потом из него делает что хочет. Это просто запись алгоритма, а для его записи очень часто все эти индексы не нужны. Если алгоритм подразумевает "для всех элементов сделать что-то", то логично это так и написать for(auto &x :  data) f(x);

1 час назад, dimka76 сказал:

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

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

ЗЫ:

Пример из жизни. В стартапе для копирования секций данных и зануления bss вот такой код на "ясном и понятном".

extern uint32_t _sidata[], _sdata[], _edata[], _sbss[], _ebss[];
 
for(uint32_t *pSrc=_sidata, *pDst=_sdata; pDst != _edata; *pDst++ = *pSrc++);
for(uint32_t *pDst=_sbss; pDst!=_ebss; *pDst++=0);

Компилятор покрутил у виска и заменил всё это на memcpy и memset соответственно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 часов назад, dxp сказал:

2. nullptr. До этого использовался 0 или макрос NULL (что то же самое)

Справедливости ради, NULL не обязательно должен иметь бинарное значение 0. Да и типовое представление могло разниться: либо просто int, либо указатель на void (если мне не изменяет память).

С остальным частично соглашусь насчет удобств, но в процессе изучения порой видишь слишком много вариантов описания одного и того же, что порождает мнение "я, в силу еще небольшого опыта, так или иначе пишу максимально криво и неэффективно, тогда нахрена мне эти приблуды, если можно в старом добром Си стиле написать?". Ну и опять же, плюсы развиваются куда стремительнее по отношению к Си, а самое главное, не всегда совместимо между версиями. Более того, комитет по стандартизации постепенно забивает на ембеддед, выводя некие перлы в релиз стандарта. Иногда перлы такие, что, почесав головы, стандартизаторы вертают взад)) Это, например, я о составных присваиваниях |= над volatile переменными в C++20.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, dimka76 сказал:

Это вообще вывих мозга и мартышкин язык

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

20 минут назад, VladislavS сказал:

В стартапе для копирования секций данных и зануления bss вот такой код на "ясном и понятном".

extern uint32_t _sidata[], _sdata[], _edata[], _sbss[], _ebss[];
 
for(uint32_t *pSrc=_sidata, *pDst=_sdata; pDst != _edata; *pDst++ = *pSrc++);
for(uint32_t *pDst=_sbss; pDst!=_ebss; *pDst++=0);

Компилятор покрутил у виска и заменил всё это на memcpy и memset соответственно.

А Вы ожидали другого? Чего?

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

23 минуты назад, Arlleex сказал:

Ну и опять же, плюсы развиваются куда стремительнее по отношению к Си

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

 

23 минуты назад, Arlleex сказал:

а самое главное, не всегда совместимо между версиями

А вот это как раз неправда. Стремление к максимальной совместимости со старым кодом (для нас это конечно хорошо) является чуть ли не основным тормозом развития языка.

23 минуты назад, Arlleex сказал:

слишком много вариантов описания одного и того же

Ничего удивительного, ведь у нас язык высокого уровня и мы пишем не инструкции процессора, а алгоритмы работы с данными. Более того, только с volatile данными! Алгоритмы можно по разному написать, это норм.

 

23 минуты назад, Arlleex сказал:

постепенно забивает на ембеддед

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

23 минуты назад, Arlleex сказал:

например, я о составных присваиваниях |= над volatile переменными в C++20

Это попытка убрать зависимые от компилятора реализации. Да, немного неудобно на старом коде в эмбедде, но мешает не сильно. Можно как переписать, так и подавить предупреждение. Понимание зачем это нужно есть.

 

23 минуты назад, Arlleex сказал:

Справедливости ради, NULL не обязательно должен иметь бинарное значение 0

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

21 минуту назад, Arlleex сказал:

А Вы ожидали другого? Чего?

Я ожидал компактного и оптимизированного цикла копирования 32-битными словами. Код с memcpy и memset получается больше и медленнее. Уж поверьте, проверено.

Неочевидное добавление вот сюда volatile делает код меньше и быстрее.

for(volatile uint32_t* pSrc = _sidata, *pDst = _sdata; pDst != _edata; *pDst++ = *pSrc++);

 

21 минуту назад, Arlleex сказал:

каждые три года надо было только нововведения проработать

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

48 минут назад, VladislavS сказал:

А вот это как раз неправда. Стремление к максимальной совместимости со старым кодом (для нас это конечно хорошо) является чуть ли не основным тормозом развития языка.

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

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

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

Цитата

Ничего удивительного, ведь у нас язык высокого уровня и мы пишем не инструкции процессора, а алгоритмы работы с данными. Более того, только с volatile данными! Алгоритмы можно по разному написать, это норм.

Не знаю, не знаю... Сколько не пытались эту самую абстрактную машину абстрагировать, а головой программистов все равно, хочешь не хочешь, заставить думать придется. Что и показательно: комитет уже лет 10 минимум пытался от volatile избавиться)) И все никак. А самое главное - зачем? Чтобы что? Писать портянки высокоуровневого кода, надеясь на то, что компилятор в хитросплетениях железячных зависимостей процессора сам разберется? Фокусы.

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

Цитата

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

Я где-то в местных разделах форума свою тему по плюсам создавал. Так у меня там вопросов был миллион, над чем в комитетах естественно подумали как раз против эмбеддед. Ну, такое чувство. Более того, на большинство вопросов как таковых ответов нет. Ответов нет - это когда их либо реально нет, либо они в стиле "так исторически хреново сделали, а комитет теперь тащит это наследие и понять не может, что с этим делать".
 

Цитата

Это попытка убрать зависимые от компилятора реализации. Да, немного неудобно на старом коде в эмбедде, но мешает не сильно. Можно как переписать, так и подавить предупреждение. Понимание зачем это нужно есть.

Нет, не появилось понимания, зачем оно нужно. Очевидно, такое же понимание непонимания появилось и у комитета, ведь в C++23 предупреждение исчезло (или нет?).
 

Цитата

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

В идеале - да. Но в реальности у нас не абстрактная машина, а реальная. С конечным числом адресуемой памяти. Очередной камень преткновения для ЯПВУ. Вроде, абстрагироваться нужно, но и нужно понимание, откуда ноги растут.
 

Цитата

Я ожидал компактного и оптимизированного цикла копирования 32-битными словами. Код с memcpy и memset получается больше и медленнее. Уж поверьте, проверено.

Это в GCC или где? Щас не могу проверить, но в Keil замечал, что если там и идет вызов memcpy, то это memcpy не тупой а хитрый, с буквенными постфиксами, маркирующими эти хитрости. Который максимально эффективный будет для данного места. Да и опять же - это Вы смотрите с оптимизацией или вообще без? К слову, без оптимизации я давно уже ни на что не надеюсь. Смотрю выхлоп только с агрессивной оптимизацией.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

57 минут назад, Arlleex сказал:

полагаю, максимум C++98, судя по году релиза бинарников

-std=c++98 

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

57 минут назад, Arlleex сказал:

пытался от volatile избавиться

С оптимизирующим компилятором в C/C++ это в принципе невозможно. Скорее это неправда.

 

57 минут назад, Arlleex сказал:

ведь в C++23 предупреждение исчезло

А говорите от эмбеддеров отвернулись :)))

57 минут назад, Arlleex сказал:

Это в GCC или где?

Это в GCC. Естественно с оптимизацией. У меня код без оптимизации не бывает в принципе. Метапрограммирование. 

57 минут назад, Arlleex сказал:

то это memcpy не тупой а хитрый

Какой бы хитрый он не был, это вызов библиотечной функции вместо тупого цикла на месте.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

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

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...