Jump to content

    

Как инициализировать массив на этапе линковки, используя относительную адресацию

Добрый день! Можно ли в современном Си++ (у меня 14) сделать следующее:

int array[] = {
  0,
  array[current_idx-1] + 2,
  array[current_idx] + 7
};
Должно получиться:
int array[] = {
  0,
  2,
  9
};

Где current_idx - это индекс текущего элемента. Другими словами мне нужно инициалиизировать элементы массива зависимыми от предыдущего элемента значениями. Перечитал кучу материала, и не смог найти решения. Спасибо)

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
3 часа назад, haker_fox сказал:

Где current_idx - это индекс текущего элемента. Другими словами мне нужно инициалиизировать элементы массива зависимыми от предыдущего элемента значениями. Перечитал кучу материала, и не смог найти решения. Спасибо)

Если можно зависимость описать формулой: Y(x) = f(x-1), то можно написать соответствующий макрос.

Share this post


Link to post
Share on other sites
15 minutes ago, jcxz said:

Если можно зависимость описать формулой: Y(x) = f(x-1)

Нет, зависимость не описывается формулой. Нужно знать именно значение предыдущего элемента массива. Но как узнать текущий индекс?

Share this post


Link to post
Share on other sites
3 hours ago, haker_fox said:

 на этапе линковки <...>  

Можно ли в современном Си++

<...>

инициалиизировать элементы массива зависимыми от предыдущего элемента значениями

Можно, используя классический препроцессор Си. "Под капотом" будет довольно монстроузно.
И строго говоря, не на этапе линковки, а перед компиляцией, на этапе препроцессирования исходного кода.
Чтобы понять, как это сделать, посоветую заглянуть в исходники библиотеки boost, подпапку preprocessor.
Начать разбираться можно начать прямо с файла boost/preprocessor/array.hpp

 

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

 

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

 

Ответить на вопрос "Зачем?"

Share this post


Link to post
Share on other sites
11 minutes ago, yaghtn said:

"Под капотом" будет довольно монстроузно.

Пожалуй слишком сложно. Пока инициализирую эти поля динамически - в рантайме.

12 minutes ago, yaghtn said:

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

А я что делаю? С этим и задаю вопрос.

13 minutes ago, yaghtn said:

Ответить на вопрос "Зачем?"

В реальности это массив из структур. Одно из полей структуры - адрес объекта. Объекты по размеру разные. И хочется записать адреса этих объектов на этапе линковки (препроцессирования, компиляции). Как-то так.

Share this post


Link to post
Share on other sites
9 минут назад, haker_fox сказал:

В реальности это массив из структур. Одно из полей структуры - адрес объекта. Объекты по размеру разные. И хочется записать адреса этих объектов на этапе линковки (препроцессирования, компиляции). Как-то так.

В исходном вопросе не было ничего про адреса чего-либо... :russian_ru:

Если все эти объекты - члены одной структуры, то вместо адресов можно хранить их смещения от начала структуры.

Share this post


Link to post
Share on other sites
4 часа назад, haker_fox сказал:

Добрый день! Можно ли в современном Си++ (у меня 14) сделать следующее:


int array[] = {
  0,
  array[current_idx-1] + 2,
  array[current_idx] + 7
};
Должно получиться:
int array[] = {
  0,
  2,
  9
};

Где current_idx - это индекс текущего элемента. Другими словами мне нужно инициалиизировать элементы массива зависимыми от предыдущего элемента значениями. Перечитал кучу материала, и не смог найти решения. Спасибо)

 

Можно. Недавно такую задачу решал - создание на этапе компиляции таблицы смещений параметров во внешней памяти по списку параметров. Посмотрите мой пример - это тестовый проект. Там много вам ненужного, но суть будет понятна. Основной файл - vault.hpp

vault.7z

Share this post


Link to post
Share on other sites
8 minutes ago, jcxz said:

В исходном вопросе не было ничего про адреса чего-либо...

Да, я хотел упростить вопрос. Чтобы люди поняли суть.

10 minutes ago, jcxz said:

Если все эти объекты - члены одной структуры, то вместо адресов можно хранить их смещения от начала структуры.

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

3 minutes ago, Nixon said:

Там много вам ненужного, но суть будет понятна

О, сейчас буду изучать! Спасибо!!!

Share this post


Link to post
Share on other sites

Весь движок в vault.hpp. Fram.hpp и eeprom.hpp - это примеры создания НЕСКОЛЬКИХ объектов хранилища (требование моего проекта). Ну а в main.cpp собственно использование с массой ненужного.

Share this post


Link to post
Share on other sites
1 hour ago, Nixon said:

создание на этапе компиляции таблицы смещений параметров во внешней памяти по списку параметров

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

 

Но если решается задача "у нас ембед, поэтому RAM мало а ROM много. Хотим держать данные в ROM",
то необходимо помнить, что значения будут разложены по адресам линкером в процессе сборки проекта,
а только потом читаться нашим кодом, и всё может расползтись.
Выравнивание, сортировка линкером объектов по имени, по типу, по размеру..  Вот это вот всё.

 

Хорошо бы строже расписать условие задачи.

Нужно массив элементов связного списка?
Или не односвязный список?  Что тогда, Дерево, ещё что?

Но взаимосвязи между элементами уже образуют структуру данных, зачем тогда массив? Или зачем взаимосвязи, когда есть массив?

Share this post


Link to post
Share on other sites

Исользуя С/С++ всегда есть возможность себе что-то отстрелить... :)

 

Задача у меня была простая - есть проект в котором некоторые переменные должны иметь зеркало во внешней памяти (назовите это конфигом, архивом, аудитом и т.п.). Желательно было иметь функционал позволяющий без дополнительных усилий изменять список этих переменных, менять их расположение (внешней памяти может быть несколько видов, несколько копий и т.д.) в одном месте. Ну и конечно, вы правильно заметили - RAM мало, ROM много, желательно иметь элемент связи между переменной и ее зеркалом расположенный в ROM. Проблемы расположения переменных линкером в данном примере НЕ имеют влияния.

 

P.S. Ранее этот движок был реализован на чистом С и требовал при модификации списка переменных изменений в 8 (!!!) местах проекта, что неимоверно раздражало, плюс таблицы адресов/типов/размеров переменных формировались в рантайме и кушали изрядный кусок RAM.

 

P.S.S. Исправил ошибку - добавил НЕ 

Share this post


Link to post
Share on other sites
25 minutes ago, yaghtn said:

Хорошо бы строже расписать условие задачи.

В моём случае всё похоже, как у уважаемого @Nixon. Каждая структура в моём массиве имеет поле - указатель на некий объект. Эти объекты расположены в памяти "как угодно", но друг за другом. Они имеют разный размер, но общего родителя. В структуре, есть также поле, по которому мы можем узнать тип объекта и его размер. Линковщик тут ни чем не поможет, т.к. содержимое массивая я могу руками в любое время поменять. По сути, мой массив со структурами, это некий аналог файловой таблицы, за которыми лежат объекты-файлы. Но это всё нужно поместить в память по-максимуму до выхода файла прошивки.

Share this post


Link to post
Share on other sites
1 hour ago, haker_fox said:

аналог файловой таблицы

Быть может стоит рассмотреть вариант, когда тип данных и размер хранится в области данных файла, а в таблице только адрес начала файла?

Хочу обратить ваше внимание, что "поле типа" в структуре с++ является известным анти-паттерном.
Шаблоном, указывающим что что-то делается неправильно. 

 

А вообще, вижу тут несколько путей:
1. Изучить С++ вплоть до платиновых вопросов "сериализация объектов в эмбеде" и "как разместить vtable в ROM"
2. Построить собственный ООП на голом С, но с блек-джеком и ROM-данными
3. Изучить как устроены файловые системы в ОС, и во взрослых типа линукса, и в легких RTOS

В итоге придёте к выводу, что на самом деле вы ищете баланс между быстродействием, требуемым объемом ОЗУ и высокоуровневостью используемого языка программирования.

Share this post


Link to post
Share on other sites
46 minutes ago, yaghtn said:

а в таблице только адрес начала файла?

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

46 minutes ago, yaghtn said:

Шаблоном, указывающим что что-то делается неправильно. 

Такое мне наследство досталось. С другой стороны, как по-другому? Ведь этим полем определяется содержимое файла. Т.е., например, это данные для видео или звука.

46 minutes ago, yaghtn said:

В итоге придёте к выводу,

Сейчас таблица заполняется во время старта кода. И всё работает, но хочется так сказать, чего-то изощрённого. Пока изучаю пример, предоставленный уважаемым @Nixon.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now