Я использую этот код некоторое время, и он отлично работает, но у меня возникла головная боль при его реализации. Он использует гибкий элемент массива (FAM) aka Struct Hack. Теперь, когда C99 имеет возможность использовать массив переменной длины (VLA), мне интересно, как я могу воспользоваться этим преимуществом?
typedef struct nO
{
int oper; /* some operator */
int nops; /* number of args */
struct nO *ptn[1]; /* expansible array <=== HERE */
} nodoOper;
nodoOper *operator(int o, int n, ...)
{
va_list ap;
nodoOper *tn;
size_t tam;
int i;
tam = sizeof(nodoOper) + (n - 1) * sizeof(nodoOper *); /* <=== AND HERE */
if((tn=malloc(tam))==NULL)
yyerror("Memory fault (cod. 4)");
tn->oper = o;
tn->nops = n;
va_start(ap, n);
for(i=0; i<n; i++)
tn->ptn[i] = va_arg(ap, nodoOper*);
va_end(ap);
return tn;
}
(Я упростил всю структуру и код здесь, потому что он использует еще две структуры, которые не важны для вопроса, поэтому, возможно, в этом примере есть ошибки)
Теперь определение структуры находится в файле заголовка (.h), а код создает дерево синтаксиса для компилятора. Как я могу изменить массив, чтобы использовать переменную длину?
Спасибо! Beco.
Отредактировано: откат последней правки к элементу гибкого массива.
2-е издание. Предположим, я добавляю внутрь функции этот фрагмент кода:
struct nOp
{
int oper; /* some operator */
int nops; /* number of args */
struct nOp *ptn[n]; /* Variable Length Array (VLA) */
};
struct nOp tnop;
struct nOp *tn2;
tn2 = &tnop;
return tn2;
Первая проблема, которую я вижу, я возвращаю указатель на локальную переменную. Но, кроме того, плодотворен ли этот путь? Спасибо
offsetof(nodoOper, ptn) + n * sizeof(nodoOper *)
для расчета размера. Таким образом, вам не нужно помнить о вычитании1
. Таким образом, вы вообще не зависите от того, что указано между[]
в объявлении массива. - person AnT   schedule 30.03.2011