В C я пытаюсь сделать следующее:
typedef struct {
int length;
int items[]; /* 1 */
} wchararray_t;
typedef struct {
long hash;
wchararray_t chars; /* 2 */
} string_t;
static string_t s1 = {
617862378,
{ 5, { 'H', 'e', 'l', 'l', 'o' } } /* 3 */
};
В полных словах мне бы хотелось, чтобы тип string_t
заканчивался другим типом wchararray_t
, который сам по себе имеет динамический размер - его размер хранится в length
. Более того, я также хотел бы написать предварительно построенную конкретную строку, как статические данные, здесь s1
длины 5.
В приведенном выше коде предполагается поддержка C99 для /* 1 */
. Включение субструктуры в большую структуру при /* 2 */
, насколько я понимаю, не поддерживается даже стандартом C99, но GCC принимает его. Однако при /* 3 */
GCC отказывается:
error: initialization of flexible array member in a nested context
В качестве обходного пути идеальный код выше до сих пор был написан как следующий хак, который "работает":
typedef struct { int length; int items[1]; } wchararray_t;
typedef struct { long hash; wchararray_t chars; } string_t;
typedef struct { int length; int items[5]; } wchararray_len5_t;
typedef struct { long hash; wchararray_len5_t chars; } string_len5_t;
static union { string_len5_t a; string_t b; } s1 = {
617862378,
{ 5, { 'H', 'e', 'l', 'l', 'o' } }
};
... и мы будем использовать "s1.b" как prebuilt string_t (и никогда не будем ссылаться на "s1.a", который здесь только для статического объявления s1). Однако он разбивается на новейший GCC 4.8, который оптимизирует части нашего кода, потому что, очевидно, любой цикл над items
для wchararray_t
может выполнять итерацию только один раз, учитывая, что это массив длиной 1.
Эта конкретная проблема исправлена, предоставив gcc опцию -fno-aggressive-loop-optimizations
. Вероятно, он также может быть исправлен, если не объявить длину в массиве wchararray_t
items[]
, что делает его динамическим массивом "только потому, что". Тем не менее, этот способ писать код - это такой хак, который я бы предпочел совершенно другим способом подойти к проблеме...
(Обратите внимание, что это все сгенерированный код C, созданный PyPy, в отличие от написанного вручную кода, любое изменение в порядке, в том числе, если оно требует изменения способа доступа к данным во всем мире, если только "действительный" C оптимизация не предотвращается.)
ИЗМЕНИТЬ: заменить "char []" на "int []", который не принимает синтаксис с двойной кавычкой "hello"
. Это потому, что я ищу решение для любого типа массива.
НЕ ПОСТАНОВИЛИ: благодарит всех за ваши предложения. Кажется, что нет чистого пути, поэтому я реализовал хакерское решение: объявляя типы k + 1 раз, один раз с помощью гибкого массива "int items []"; и k в других случаях с "int items [N];" для различных значений N, которые необходимы. Это требует некоторых дополнительных хаков: например. не используя гибкие массивы для MSVC (они работают по-разному там, я не исследовал, знаю ли точно такой же синтаксис); и GCC следует тому, что C99 говорит и недовольна структурами, которые содержат int items[];
как только поле. Тем не менее, мы счастливы, если добавить фиктивное поле char _dummy[0];
... которое не является строго C99, насколько я знаю...