Dmitry Develop
176 subscribers
77 photos
35 videos
88 files
205 links
Этот канал в основном будет интересен новичкам в программировании и людям немного поопытнее.
Здесь я буду делиться своими новостями и достижениями в программировании.

Разработка, программирование; c++, gcc, g++, gnu, mingw; winapi, windows; vscode.
Download Telegram
image_2023-11-10_09-53-28.png
72.2 KB
ссылка на канал | ссылка на группу
Dmitry Develop
image_2023-11-10_09-53-28.png
Увеличил глубину и частоту дискретизации передачи сигнала с микроконтроллера на ПК с 8 до 16 bit и с 500 до 5000 Hz.

Было как-то неприятно увеличивать количество передаваемых байт с 4 до 8, но производительности микроконтроллера, ПК и моего кода хватило.
И я до последнего был уверен, что всё сломается, появится трудноуловимый баг или вообще ошибка сегментации, когда я перепишу код обработки данных на новый протокол общения.

Ну а ещё я постепенно чиню полосу прокрутки.
Сейчас уже правильно вычисляется размер ползунка, ничего не ломается, если указать диапазон [0, -N], и правильно вычисляется даже отрицательный отступ.

ссылка на канал | ссылка на группу
IMG_20231121_161136.jpg
3.3 MB
ссылка на канал | ссылка на группу
1
Dmitry Develop
IMG_20231121_161136.jpg
Наконец-то приехала небольшая поддержка от спонсора нашего общего проекта).

ссылка на канал | ссылка на группу
ссылка на канал | ссылка на группу
Dmitry Develop
ссылка на канал | ссылка на группу
Сегодня я открыл для себя новый инструмент, который делает сгенерированный компилятором ассемблерный код более читаемым.

Если вы когда-нибудь смотрели преобразованный С++ код в ассемблерный код или видели сообщение об ошибке "undefined reference to _Z7timeNowPx", вы могли заметить, что привычное название функции, например, timeNow(uint64*) превращается в _Z7timeNowPx.

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

Этот механизм называется name mangling.
Он нужен для того, чтобы компоновщик (linker) мог различать символы с одинаковыми названиями, перегрузки функций и не только, создавая для каждого символа уникальное неповторяющееся название.

Чтобы преобразовать mangled символы в читаемый вид, нужна программа c++filt.exe, которая поставляется вместе с компилятором gcc.
При запуске программа будет ожидать текст в потоке ввода и выводить в консоль преобразованный текст.
Так как она не умеет работать с файлами напрямую, нужно перенаправить поток ввода и вывода:
c++filt.exe < mangled.asm > demangled.asm

Это работает так:
Запускается программа c++filt.exe, в поток ввода передаётся содержимое файла mangled.asm и потом вывод программы перенаправляется в файл demangled.asm.

Предыдущую конструкцию вообще можно объединить в одну строчку с генерацией ассемблерного кода:
g++.exe -S -masm=intel -fverbose-asm -o mangled.asm main.cpp && c++filt.exe < mangled.asm > demangled.asm

Как объединить несколько команд и перенаправить ввод-вывод в вашем терминале и операционной системе ищите самостоятельно:
"chain commands in terminal"
"terminal redirect input output"

Более сложный пример:
_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE15_M_replace_coldEPcyPKcyy

std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_replace_cold(char*, unsigned long long, char const*, unsigned long long, unsigned long long)

ссылка на канал | ссылка на группу
🔥2🤯1
Раньше здесь был ъуъ).

...
Недавно я делал лабораторную работу, в которой надо было в runtime создавать одно- и многомерные массивы (1D, 2D, 3D) большого размера, заполнять их: последовательными значениями по возрастанию, по убыванию и перемешанными значениями (shuffle), а потом применять к ним различные алгоритмы сортировки.

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

Способов передачи массивов в функцию довольно много: от написания шаблонной функции до передачи типа int (*row)[10].
У каждого способа были свои преимущества и недостатки: один был сложным, второй подходил только для массивов фиксированного размера, третий вообще активно использовал UB (но я не уверен).

Потом я вспомнил, что в Си / С++ массивы в памяти хранятся построчно (row-major order):
// многомерный массив
int array[3][2][3]
{
{
{
{ 1, 2, 3 }
},
{
{ 4, 5, 6 }
}
},
{
{
{ 7, 8, 9 }
},
{
{ 10, 11, 12 }
}
}
{
{
{ 13, 14, 15 }
},
{
{ 16, 17, 18 }
}
},
};
// представление в памяти
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18


Многомерный массив привести к одномерному и соответственно вычислить индекс:
// было:
array[k][j][i]
// стало:
array[k*Y*X + j*X + i]


Поэтому я решил, что массив от 1 до 3 измерений (можно и больше), я буду выделять так:
// было:
new int[z][y][x] { };
// стало:
new int[z * y * x] { };


Заметьте, что, в привычном виде для разработчиков игр и графики, оси вектора (размерности) перечисляются в таком порядке: x, y, z.
А единичные векторы, из суммы которых можно представить любой вектор, в таком: i, j, k.
Но в C++ размерности надо указывать задом наперёд.

В итоге, чтобы передать такой flatten массив в функцию достаточно будет:
void arrayModify(int* array, const int x, const int y = 1, const int z = 1);


Можно было создавать не двумерный массив, а массив указателей на одномерные массивы.
Но это сложнее: надо создавать сначала массив указателей, потом через цикл создавать массив строк и удалять соответственно в обратном порядке.
Такой массив можно передавать в функцию, как int** array.
Но как дело доходит до трёхмерного... оно того не стоит.
Да и универсальный алгоритм сложнее написать, если вовсе невозможно.

ссылка на канал | ссылка на группу
👍3🕊1
Я заметил, что в последнее время я в основном пишу всё в группу, но не в канал.

Хотя канал был создан, чтобы делиться с другими чем-то по тематике около С++, электроники и техники.
Ну, а ещё чтобы не доставать своих друзей и близких часовыми лекциями по поводу языка С++ и моих проектов)).

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

Что думаете, я из пустяка сделал себе проблему?
И стоит просто забить и выкладывать почти всё в канал после вычитки и всех правок?

ссылка на канал | ссылка на группу
Что ж, предыдущее случайное недоразумение я переписал:
https://t.me/a248640develop/155

ссылка на канал | ссылка на группу
Dmitry Develop
projectHierarchy.png
Переделываю с нуля шаблон проекта на C++ для vs code.
Дело дошло до настроек внешнего оформления и создания иерархии проекта.

Хочется в шаблоне проекта указать ключи компилятора для подключения какой-нибудь самописной или сторонней библиотеки.

Вопрос в том, какую иерархию проекта сделать?
Сделать папку library и туда класть скомпилированные библиотеки, но куда класть header файлы?
Не хотелось бы перемешивать файлы проекта с файлами библиотеки.

Может, разбить проект как бы контейнеры, где у каждого контейнера есть свои исходные и заголовочные файлы?
project
| main
| | source
| | | *.cpp
| | include
| | | *.hpp
| library1
| | source
| | | *.cpp
| | include
| | | *.hpp
| library2
| | source
| | | *.cpp
| | include
| | | *.hpp

ссылка на канал | ссылка на группу
Dmitry Develop
IMG_20231213_213456.jpg
Как же мне нравится качество китайских товаров.

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

Первым делом я подумал, что в поломке гирлянды виноват сетевой фильтр, который я недавно паял.
Разобрал коробочку, от туда продолжает идти чёрный дым, пахнет чем-то горелым.
Четверть площади платы покрылась копотью.
Я даже и не заметил сразу, что отгорели два провода сетевой вилки.

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

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

Сегодня обойдусь без сложных ремонтов и выбрасывания в мусорку).

ссылка на канал | ссылка на группу
Dmitry Develop
image_2023-12-14_15-40-50.png
Можно было сделать и лучше; с параметрами, мне кажется, немного беда.
Зато у меня получилось хорошее именование функций, мне нравится что всё сделано по общему шаблону.

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

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

Просто я немного изменил иерархию проекта и решил заодно ещё и команду сборки переписать.

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

И это не самый страшный случай.
Хуже всего было только тогда, когда я свой старый игровой движок, код которого был написал под компилятор msvc несколько лет назад, попытался скомпилировать при помощи последнего g++.
Было очень много ошибок и предупреждений, и даже спустя час правок файлов по всему проекту, мне так и не удалось его скомпилировать.

ссылка на канал | ссылка на группу
Dmitry Develop
image_2023-12-16_02-13-50.png
Что делать, если во время отладки в vs code вместо содержимого STL контейнера видна его внутренняя реализация?

На фото выше в порядке сверху вниз: сам код, вид std::vector в отладчике до и после изменений.

Надо просто в launch.json добавить "setupCommands", чтобы перед запуском отладки передать в gdb один ключ:
// launch.json
{
"version": "0.2.0",
"configurations":
[
{
...

"setupCommands":
[
{
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],

...
}
]
}


Вообще, если разбираться подробнее как это работает, всё довольно сложно.
Похоже, перед представлением данных, gdb или адаптер использует скрипты на python.

ссылка на канал | ссылка на группу
Я всегда предпочитал сложный путь лёгкому, стандартному решению — нестандартное, поверхностному изучению — углублённое.

Благодаря этому я уже сейчас знаю или умею то, что другие узнают или научатся только в будущем.

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

Поэтому я хочу предложить свою помощь в вопросах, связанных с компилятором mingw (gcc), редактором кода vs code, написания лабораторных работ, программирования на C++, решения проблем с кодировками и другими распространёнными проблемами.

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

Я свой уровень С++ оцениваю где-то между junior и middle: у меня довольно выборочные знания и умения: где-то поверхностные, где-то углублённые.
Поэтому каждый вопрос разбираю индивидуально и помогу, чем смогу.

Буду рад за свою помощь получить вознаграждение.
Оплату принимаю на российскую карту или в криптовалюте.

ссылка на канал | ссылка на группу
🤡5