【问题标题】:Flexible array member (c99) inside a structure结构内的灵活数组成员 (c99)
【发布时间】:2011-07-25 14:56:48
【问题描述】:

我使用这段代码已经有一段时间了,它运行良好,但实现它让我有些头疼。它使用灵活数组成员 (FAM) 又名 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) 中,代码为编译器创建语法树。如何更改数组以使用可变长度?

谢谢! 贝科。

已编辑:将上次编辑回滚到灵活数组成员。

第二版。假设我在函数内部添加了这段代码:

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;

我看到的第一个问题,我正在返回一个指向局部变量的指针。但除此之外,这条路是否硕果累累? 谢谢

【问题讨论】:

  • 现在我了解到 Flexible Array Member (FAM) 是 Struct Hack 的同义词,并且我已经这样做了,我很清楚这个问题的目的是找到使用 C99 给我们的另一个工具的另一种方法称为可变长度数组 (VLA)。如果这不可能,那么……好吧,我们保留已经实施的旧方法。
  • 如果您决定保留“旧方式”,您可以考虑使用offsetof(nodoOper, ptn) + n * sizeof(nodoOper *) 来计算大小。这样你就不需要记住减去1。这样你就完全不依赖于数组声明中[] 之间指定的内容。

标签: c arrays c99


【解决方案1】:

其实这里要使用的不是变长数组,而是struct hack,又名“不完整类型”,又名“灵活数组成员”:

typedef struct nO
{
    int oper;
    int nops;
    struct nO *ptn[];  // <== look ma, no index!
} nodoOper;

// skip a bit
// no more (n-1) --------\
tam = sizeof(nodoOper) + n * sizeof(nodoOper *);

只有struct 的最后一个成员可能是“灵活的”。

可变长度数组是一个不同的特性:

void foo(int size)
{
    float a[size];               // run-time stack allocation
    printf("%lu\n", sizeof(a));  // and run-time sizeof (yuck)
}

(哦,这些东西叫做数组,而不是矩阵。)

【讨论】:

  • “哦,这些东西叫做数组,不是矩阵”——哈哈
  • :) 好的!我会更正帖子。正如@pmg 所说,该名称对于帮助在网络中进行搜索很重要。
  • 感谢 larsmans,但它仍然需要 malloc。我的意图是完全消除 malloc。还有其他选择吗?
  • @Dr Beco:不,你不能以这种方式摆脱malloc。毕竟,如果您确实使用 VLA,则可以摆脱 malloc,但这在 struct 中不起作用。
  • @larsman, tam 应该是要分配的大小?这有点错误...sizeof(nodoOper) + n * sizeof(struct nO*) 甚至更好的offsetof(nodoOper, ptn) + n * sizeof(struct nO*) 甚至更好的是maxsizeof(nodoOper) 的真正正确公式。
【解决方案2】:

该构造的 C 名称是“灵活数组成员”(它可能有助于您的搜索),或 C99 之前的“struct hack”

Standard中的6.7.2.1;文中有示例用法。


您可能还对“可变长度数组”感兴趣。请参阅标准中的 6.7.5.2。

【讨论】:

  • 我可能在编辑时犯了一个错误。我认为现在正确的是可变长度数组。
  • 也在“structhack”下的索引中列出:)
  • 肯定不是灵活数组成员的情况。
  • 我认为你有一个 FAM,@DrBeco。 larsmans answer中的示例应该让您轻松入门。
  • 很抱歉有这么多版本。我已经完成了问题标题的编辑。我正在为一些我什至不知道名字的事情寻求帮助。再次抱歉,伙计们。
猜你喜欢
  • 2011-03-04
  • 1970-01-01
  • 1970-01-01
  • 2020-04-13
  • 2014-07-29
  • 1970-01-01
  • 2012-11-22
  • 2012-09-22
  • 1970-01-01
相关资源
最近更新 更多