инициализация массива C с повторяющимися данными - PullRequest
5 голосов
/ 10 мая 2009

Я хотел бы инициализировать массив структур с одним и тем же элементом, то есть

struct st ar[] = { {1,2}, {1,2}, {1,2} };

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

Это имеет смысл, когда массив используется в качестве мини-базы данных ad-hoc (сопоставляет id со структурой) и когда требуется использовать значение по умолчанию для всех значений базы данных.

Моим лучшим решением было использовать что-то вроде

#define I {1,2}
struct st ar[SIZE_OF_ARRAY] = { I,I,I };

Так что компилятор предупредит меня, если у меня слишком много или слишком мало I с. Но это далеко от идеала.

Я думаю, что в ANSI-C для этого нет решения, но я подумал, что, возможно, есть макрос, или расширение gcc, которое сделает эту работу. В идеале мне бы хотелось стандартное решение, но даже конкретных компиляторов было бы достаточно.

Я думал, что каким-то образом смогу определить макрос рекурсивно, чтобы I(27) было разрешено до 27 {1,2} с, но я не думаю, что это возможно. Но, может быть, я ошибаюсь, есть ли взломать для этого?

Может, встроенная сборка сработает? Было бы очень легко определить такой макет памяти с помощью MASM или TASM, но я не уверен, что можно встроить инструкции макета памяти в код C.

Есть ли какой-нибудь трюк с компоновщиком, который соблазнил бы его для инициализации памяти в соответствии с моими приказами?

PS Я знаю Я могу автоматически генерировать C-файл с помощью некоторого сценария. Использование пользовательских сценариев нежелательно. Если бы я использовал собственный скрипт, я бы изобрел C-макрос REP(count,exp,sep) и написал бы мини-C-препроцессор, чтобы заменить его на exp sep exp sep ... exp {exp appears count time}.

Ответы [ 5 ]

10 голосов
/ 10 мая 2009

Библиотека препроцессора boost (которая отлично работает на C) может помочь.

#include <boost/preprocessor/repetition/enum.hpp>

#define VALUE(z, n, text) {1,2}

struct st ar[] = {
    BOOST_PP_ENUM(27, VALUE, _)
};

#undef VALUE

Если вы хотите использовать его, вам просто нужен каталог boost/preprocessor от boost - он полностью автономен.

Хотя, у него есть некоторые произвольные ограничения на количество элементов (я думаю, что в данном случае это 256 повторений). Существует альтернатива chaos , которая не работает, но является экспериментальной и будет работать только для препроцессоров, которые точно соответствуют стандарту (GCC's).

5 голосов
/ 10 мая 2009

Самый простой способ, о котором я могу подумать, - это написать скрипт для генерации инициализаторов, которые вы можете включить в свой код C:

{1,2},
{1,2},
{1,2}

Тогда в вашем источнике:

struct st ar[] = {
    #include "init.inc"
};

Вы можете настроить Makefile на автоматическое генерирование, если хотите.

2 голосов
/ 10 мая 2009

Я предполагаю, что вы можете, для файла с определением массива, сделать:

#include "rep_array_autogen.c"
struct st ar[SIZE_OF_ARRAY] = REPARRAY_DATA;

и ваш Makefile генерирует rep_array_autogen.c в формате, подобном

#define SIZE_OF_ARRAY 3
#define REPARRAY_DATA {{1, 2}, {1, 2}, {1, 2}, }

Поскольку на вашем компьютере установлена ​​rep_array_autogen.c, это будет так же быстро, как и ручное кодирование.

0 голосов
/ 10 марта 2010

Элазар,

Можете ли вы предоставить данные, подтверждающие ваше мнение, что предварительно инициализированные данные быстрее, чем инициализация во время выполнения?

Если вы выполняете код на стандартном компьютере с жестким диском (HDD), а ваша программа находится на жестком диске, тогда время для копирования данных из раздела данных вашего двоичного образа в ОЗУ, по существу, равно времени с использованием некоторого типа инициализации во время выполнения.

Кип Лейтнер

0 голосов
/ 10 мая 2009

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

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

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