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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Друг Кота
Аватара пользователя
Сообщения: 7360
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

А. дошло. никак не мог додуматься зачем нужно имя при определении типа. Теперь понял.
Реклама
Открыл глаза
Сообщения: 60
Зарегистрирован: Вс ноя 13, 2022 14:58:17

Сообщение Bill_ »

[uquote="uldemir",url="/forum/viewtopic.php?p=4394254#p4394254"]Как переключать контекст я и так знаю - там проблема в цикличной зависимости определений друг от друга. Которая не проблема для, говорят, C++, но чистый C такого не позволяет. А про связный список я не настаивал, но мне его предложили и хочу знать.
...как написать связный список на си? Чтобы линки создались уже на этапе компиляции. И чтобы не выдумывать каждой записи уникальное имя. Или как в этом кадре из видео,
Изображение
не нужно было в случае, если захочу вставить команду между "s" и "g" переправлять в каждой строчке &LL[3] на &LL[4], затем &LL[4] на &LL[5] и так далее до 85-го элемента массива.

И еще, чтобы длина строки содержащей команду не была константной. но typedef, кажется, такое не приемлет.[/uquote]
Пример вы привели, мягко сказать, неудачный. Для начала нужно понять что собой представляют массивы и списки, и для чего они могут быть использованы.
Прежде всего, с точки зрения использования памяти, массивы являются статическими объектами. Т.е требуемый объём памяти определяется на этапе компиляции. Допустим, вы хотите сделать словарь на определённо количество слов и оформили его в виде массива. В этом случае вы не сможете в процессе работы программы увеличить количество слов в словаре, если это потребуется. Можно конечно на этапе компиляции сделать размер массива больше, чем требуется изначально. Скажем на момент компиляции в словаре имеется 10 слов, но вы сделаете массив на 100 слов, в расчёте на то, что в процессе работы программы словарь может быть увеличен. Но при этом могут возникнуть две проблемы. Во-первых нет гарантии, что этого массива может хватить (скажем, вы предполагали увеличение словаря до 100, а понадобилось 101 слово). Во-вторых, память будет использоваться не рационально, если количество слов в словаре будет меньше, чем вы расчитывали.
Теперь о списках. В противоположность массивам, списки являются динамическими объектами. Изначально список может вообще быть пустым и никакой памяти выделять не потребуется. Элементы списка создаются и добавляются к списку во время работы программы. Но ту возникает вопрос: а где взять необходимую память? Ответ - память берется из так называемой "кучи", которая обычно имеется в системе. Для этой цели в библиотеки Си имеются соответствующие функции, например malloc (выделить память) и free (освободить память). Но при этом для работы со списками потребуются дополнительные программы.
Наиболее часто связные списки используются в различных трансляторах, когда количество символов в транслируемой программе заранее неизвестно.
Теперь об инициализации списков. В приведённом вам примере список вообще не нужен, ибо все элементы статические. Здесь лучше использовать обыкновенный массив. И памяти меньше потребуется, и работать с массивом будет проще. Что же касается инициализации самих списков на этапе компиляции не необходимости указывать адрес следующего элемента в списке, поскольку этот адрес будет определяться в процессе создания списка при работе программы. Ниже приводится фрагмент программы инициализации списка. На этапе компиляции определяются только те элементы списка, которые должны быть в списке изначально.

Код: Выделить всё

    add_sym("ADC", I_ADC, OC_LD, &instruction_section, &system_st);
    add_sym("ADD", I_ADD, OC_LD, &instruction_section, &system_st);
    add_sym("ASL", I_ASL, OC_1GEN, &instruction_section, &system_st);
    add_sym("ASR", I_ASR, OC_1GEN, &instruction_section, &system_st);
    add_sym("LSL", I_LSL, OC_1GEN, &instruction_section, &system_st);
    add_sym("LSR", I_LSR, OC_1GEN, &instruction_section, &system_st);
    add_sym("BCC", I_BCC, OC_BR, &instruction_section, &system_st);
    add_sym("BCS", I_BCS, OC_BR, &instruction_section, &system_st);
Функция add_sym как раз используется для добавления к списку. При этом последовательность добавления элементов в список может быть произвольной.
Последний раз редактировалось Bill_ Сб апр 01, 2023 08:23:02, всего редактировалось 1 раз.
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Связанный свитер, а список связный. А так, в целом верно. Разве что, память не только в куче можно взять.
Открыл глаза
Сообщения: 60
Зарегистрирован: Вс ноя 13, 2022 14:58:17

Сообщение Bill_ »

[uquote="VladislavS",url="/forum/viewtopic.php?p=4394562#p4394562"]Связанный свитер, а список связный. А так, в целом верно. Разве что, память не только в куче можно взять.[/uquote]
Исправил. :)
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 7360
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

Ну, это всё понятно. пополнение списка у меня не предполагается. потому как это не настоящий форт, а всего-лишь способ интерпретации команд. Очень простой, причем. Почему я кошусь в сторону списков? Хочется избавиться от ограничения на длину строки. Для интерпретатора нуль-терминированная строка вполне подходит (тем более что у меня сейчас это сделано также - сравнение либо до '\0', либо до 12-го символа). Но массив, как вы сказали, имеет жёстко заданные размеры. И для того чтобы иметь возможность с этим справиться и может помочь список. Почему меня не устраивает применение "add_sym()" - из-за того, что тогда этот "список" будет в двух местах и в ПЗУ, и в ОЗУ. И еще нужно будет ждать пока он проиницализируется при старте.
Реклама
Открыл глаза
Сообщения: 60
Зарегистрирован: Вс ноя 13, 2022 14:58:17

Сообщение Bill_ »

[uquote="uldemir",url="/forum/viewtopic.php?p=4394571#p4394571"]Ну, это всё понятно. пополнение списка у меня не предполагается. потому как это не настоящий форт, а всего-лишь способ интерпретации команд. Очень простой, причем. Почему я кошусь в сторону списков? Хочется избавиться от ограничения на длину строки. Для интерпретатора нуль-терминированная строка вполне подходит (тем более что у меня сейчас это сделано также - сравнение либо до '\0', либо до 12-го символа). Но массив, как вы сказали, имеет жёстко заданные размеры. И для того чтобы иметь возможность с этим справиться и может помочь список. Почему меня не устраивает применение "add_sym()" - из-за того, что тогда этот "список" будет в двух местах и в ПЗУ, и в ОЗУ. И еще нужно будет ждать пока он проиницализируется при старте.[/uquote]
Используйте в элемента не массив символов, а указатель на него. Например, вместо

Код: Выделить всё

char word[12];

Код: Выделить всё

char *word;
Хотя инициализация массива будет выглядеть одинаково.
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="uldemir",url="/forum/viewtopic.php?p=4394571#p4394571"]Почему я кошусь в сторону списков? Хочется избавиться от ограничения на длину строки.[/uquote]У вас не хватает памяти? Пусть у вас три десятка элементов в среднем занятых на половину. 30х6=180 байт лишних. Вы уверены, что функции работы со связным списком займут меньше? Пока что это выглядит как преждевременная оптимизация.
Друг Кота
Аватара пользователя
Сообщения: 7360
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

В своё время (лет эдак 30 назад) Харий Буш говорил про винчестеры, что скорость их заполнения является константой и от объёма диска независящая. Так же и с памятью. Когда-то хватало 4 килобайт, сейчас и в 128 становится тесно. Хотя новый проект идёт на кристалле с 1.5М флеша и 0.5М озу. Но если серьёзно, хочется научиться разным техникам просто из интереса. И честно, мне плевать, сколько это памяти съест, а как это внятно написать в программе, чтобы было легче её "сопровождать". Я мог бы оставить строку с ограниченной длинной, и когда мне захотелось бы добавить слово "init_brakepath" тогда пришлось бы думать, сократить эту команду на 2 символа или в определении поменять 12 на 14. А так, я даже еще потерял 4 байта памяти на указатель к строке, но зато можно не ломать голову что делать.
СпойлерСобственно, всё это началось с того, что взяв проект двухлетней давности я не мог вспомнить, как пользоваься некоторыми командами и поэтому захотелось добавить команду "help", которая мне напомнила бы, как та или иная команда работает. Т.е. help переключает контекст и команда init_brakepath не инициализирует таблицу тормозного пути, а рассказывает, что она будет делать. Так что важнее читаемость программы для дальнейшей модификации, а не объём памяти (хотя его тоже нельзя брасывать со счёт). Читаю тут что на C++ это можно делать гораздо продвинутей, но я еще сам не настолько продвинут
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Посмотрите, как делал я в своём проекте FlexMenu, там на этапе компиляции собираются массивы со строковыми константами произвольной длины. Там, кстати, есть и еще некоторые моменты, которые, как мне кажется, могут вам пригодиться. Если с макросами разберетесь, конечно...
А из проекта DigiScript можете использовать идею "массивов без явного описания и с инициализацией элементов в любом месте проекта". В этом проекте, кстати, я как раз интерпретатор и делал.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

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

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

2. Набиваем глобальных объектов
Изображение

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

4. Например, поиск в такой "структуре" по индексу
Изображение

И никакие связные списки для константных данных этапа компиляции, само собой, тут не нужны. Каждый инструмент предназначен для своих задач.
Спойлер
изображение_2023-04-01_125710093.png
(13.67 КБ) 552 скачивания
изображение_2023-04-01_125920771.png
(10.53 КБ) 544 скачивания
изображение_2023-04-01_130154999.png
(4.97 КБ) 550 скачиваний
изображение_2023-04-01_130635725.png
(4.95 КБ) 508 скачиваний
Друг Кота
Аватара пользователя
Сообщения: 7360
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

Вопрос по ардуине. Есть функция в файле motors.cpp

Код: Выделить всё

void set_motor_pwm_frequency(int frequency) {
  switch (frequency) {
    case PWM_31250_HZ:
      // Divide by 1. frequency = 31.25 kHz;
... 
      break;
    case PWM_3906_HZ:
      // Divide by 8. frequency = 3.91 kHz;
...
      break;
    case PWM_488_HZ:
    default:
      // Divide by 64. frequency = 488Hz;
...
      break;
  }
}
вызывается просто:

Код: Выделить всё

set_motor_pwm_frequency();
Я бы подумал, что установится частота 488Гц. Но в хидере она объявлена так:

Код: Выделить всё

/***
 * @brief set the motor pwn drive to one of three possible values
 */
void set_motor_pwm_frequency(int frequency = PWM_31250_HZ);
Это что значит? в плюсах я ничего не понимаю.
Друг Кота
Аватара пользователя
Сообщения: 15605
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

"аргумент по умолчанию" - если ничего в аргументах не указывается пользователем будет использовано значение по умолчанию.
8)
OKF
Это не хвост, это антенна
Сообщения: 1407
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

[uquote="uldemir",url="/forum/viewtopic.php?p=4409235#p4409235"]Но в хидере...[/uquote]
Не в хидере, а в хедере! "Карту купи..."
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32

Сообщение Martian »

ну, тогда уж правильно в хеде, без р
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 7360
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

Лучше бы по делу что написали, что произойдёт, если этот хи... пусть будет так: motors.h не будет включен в motors.cpp.
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32

Сообщение Martian »

ну как что? если заголовочный файл не будет подключен, область видимости объявленных в нем переменных и функций и значения дефайнов изменятся. В случае переменных и функций будет фатальная ошибка (впрочем, с функциями не всегда), в случае дефайнов - или фатальная, или логическая (если они где-то ещё такие же есть, но с другими значениями).
Здесь, если компилятор увидит функцию раньше вызова, ошибки не будет, но значение по умолчанию потеряется.
Контактная информация:
Встал на лапы
Сообщения: 81
Зарегистрирован: Пт май 14, 2021 22:25:07

Сообщение zx_gamer »

Я вижу тут народ списки обсуждал. TL;DR.
Чем не устраивает плюсовый std::list? Список, конечная самая простая из сложных структур данных, но реализовывать функции для работы с ней с нуля муторно.
Кстати, совет, можно написать список полностью в максросах (как шаблоны на Си++) и тогда можно будет не копипастить их для разных типов данных.
Встал на лапы
Аватара пользователя
Сообщения: 145
Зарегистрирован: Пн апр 02, 2012 15:56:23

Сообщение azhel12 »

[uquote="zx_gamer",url="/forum/viewtopic.php?p=4412126#p4412126"]Чем не устраивает плюсовый std::list?[/uquote]
Думаю, что не ошибусь, если скажу, что среднему программисту гораздо проще написать свою реализацию списка (хоть на си, хоть на плюсах с шаблонами), чем свой кастомный аллокатор для STL-контейнеров.
Друг Кота
Аватара пользователя
Сообщения: 7360
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

Снова глупый вопрос. Для расчета тормозного пути мне надо вычислить разность квадратов a²-b². В целочисленных вычислениях я использовал формулу (a-b)*(a+b) - два сложения и одно умножение. А как лучше считать для плавующей точки, если у процессора есть FPU? имеется в виду - два умножения и сложение или два сложения и умножение - что будет быстрее.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

Мой уютный бложик... заходите!
Контактная информация:
Ответить

Вернуться в «Разные вопросы по МК»