2016-02-22 2 views
2

Скажем, у меня есть этот код:Размер гибкого элемента массива с брекет инициализацией

const struct 
{ 
    const char * const name; 
    const unsigned length; 
    const char data[951357]; 
} var[] = 
{ 
    { 
    "dataset1", 
    #include "dataset1.h" 
    }, 
    { 
    "dataset2", 
    #include "dataset2.h" 
    }, 
    /* ... */ 
}; 

Каждый dataset*.h содержит что-то вроде:

6, 
{ 
    0x04, 0x08, 0x15, 0x16, 0x23, 0x42 
} 

Это требует, чтобы я заранее знать размер самого крупного набор данных. Это не соответствует будущему, поскольку любой, кто добавляет набор данных, также должен проверять и, возможно, изменять размер data и может привести к серьезным потерям памяти (в моем реальном случае уже существует ~ 15 наборов данных с размерами в пределах сотни КБ).

Есть ли способ обойти это?

Единственное жесткое требование состоит в том, чтобы каждый данные должны быть в собственном файле, но формат этого файла может быть любым. Я также хотел бы сохранить все как можно const.

Edit: я должен отметить, что старый код делает это:

struct dataset { char* name; int length; char* data; }; 
struct dataset *alldata[10]; 
struct dataset dataset1 = { 
    "dataset1", 
    #include "dataset1.h" 
}; 
/* same again for every dataset */ 
int main() 
{ 
    alldata[0] = malloc(sizeof(struct dataset)); 
    memcpy(alldata[0], dataset1, sizeof(struct dataset)); 
    /* again, block copied for each dataset */ 
} 

Этот код выглядит некрасиво со мной, и требует (я думаю) ненужные копии MEM. Моя цель при перезаписи этого кода заключалась в том, чтобы он хранил все данные во время компиляции, а затем читал их только при необходимости во время выполнения.

+1

Должен ли массив быть внутри структуры? Достаточно ли указателя? – user694733

+0

Обязательны ли все эти 'const' вокруг вашего определения' struct'? – LPs

+1

'const char const * name;' похоже на ошибку. Возможно, вы имели в виду 'char const * const name;'? Кроме того, для массива требуется только один: 'char const data [951357];'. – user694733

ответ

1

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

#include "dataset1.h" 
/* other dataset includes here */ 
struct DataSet { 
    const char * name; 
    unsigned length; 
    const char * data; 
}; 
const struct DataSet var[] = { 
    { 
     "dataset1", 
     dataset1_length, 
     dataset1_data, 
    }, 
    /* other dataset inits here */ 
}; 

dataset1.h

enum { dataset1_length = 6 }; 
extern const char dataset1_data[]; 

dataset1.c

const char dataset1_data[] = { 0x04, 0x08, 0x15, 0x16, 0x23, 0x42 }; 

Обратите внимание, как я удалил ненужные const с, но все данные по-прежнему const.

Если иметь дополнительные единицы компиляции не хотел, просто объединить заголовок и исходный файл в один заголовок и включают в себя, что непосредственно:

dataset1.h

enum { dataset1_length = 6 }; 
const char dataset1_data[] = { 0x04, 0x08, 0x15, 0x16, 0x23, 0x42 }; 
+0

Я пробовал что-то подобное, но компилятор жаловался на 'dataset1_data', не являющийся compile-time const (или что-то в этом роде, я точно не помню). Я попробую еще раз, может быть, я просто помещал свой 'const' в неправильные места :) – 1ace

+0

@ 1ace Возможно, это как-то связано с данными' char *, 'не является' const' в вашем старом коде? – user694733

+0

Я идиот: проблема заключалась в том, что 'length' не является константой времени компиляции, а не' data':] – 1ace

1

Вы хотите создать массив структур , Массив требует, чтобы размер каждого элемента был одинаковым. Сказал, что вы не можете создать какой-либо массив, используя структуры разных размеров, из-за гибкого массива, если вы не исправите размер члена массива (как вы это делаете). Существует решение в любом случае. Измените элемент массива переменной длины указателем и создайте массив переменных размера в другом месте.
Решение, которое я объясню, позволит вам продолжать использовать метод доступа к массиву, поэтому вам не нужно менять остальное программное обеспечение и требует небольшой модификации ваших файлов заголовков.
Основная структура декларации будет тогда:

const struct 
{ 
    const char const * name; 
    const unsigned length; 
    const char const *data; //This is the only difference 
} var[] = 
{ 
    { 
    "dataset1", 
    #include "dataset1.h" 
    }, 
    { 
    "dataset2", 
    #include "dataset2.h" 
    }, 
    /* ... */ 
}; 

файлы заголовков будут обработаны следующим образом:

6, 
(const char const *)&(const char[]) {0x04, 0x08, 0x15, 0x16, 0x23, 0x42} 

Здесь часть (const char[]){0x04, 0x08, 0x15, 0x16, 0x23, 0x42} создает в памяти массив char констант переменной длины. Затем с оператором & мы получаем его адрес и передаем его указателю char перед назначением его структуре.
Протестировано под C99-C11