【问题标题】:Variable sized structures within another variable sized structure另一个可变大小结构中的可变大小结构
【发布时间】:2015-03-19 17:01:02
【问题描述】:

我在可变结构中有可变大小的结构。走每个子表的好方法是什么?缓冲区是字节打包的,在“地址”处可用。无需malloc。不能在while循环中做索引,用表大小偏移是唯一的选择吗?


void walk_master_table (ulong address)
{
    int count=0;
    Master_table* masterTable = (Master_table*)address;

    while(masterTable->subTables[count].subTable1.length)
    {
        //do some processing;
        // advance to next sub table

        count ++;  /* <-- I cannot do this because the offset is not */
                   /*guaranteed and the buffer is byte-packed*/
    }
}


struct Master_table
{
    uint Total_MasterTable_Length;
    struct SUB_TABLES subTables[1];
}

struct SUB_TABLES 
{
   union {
    struct subTable1;
    struct subTable2;
    struct subTable3;
    struct subTable4;
    char buffer[128];
    };
}

/*each subtable is of different size.*/

struct subTable1
{
    uint thisTable_length;
    char [xx];
}

struct subTable1
{
    uint thisTable_length;
    char [yy];
}

struct subTable3
{
    uint thisTable_length;
    char [zz];
}

【问题讨论】:

  • 不存在可变大小的结构。您的 strict Master_table 大小是 sizeof(uint) + sizeof(struct SUB_TABLES) 加上所需的任何填充(在这种情况下可能没有)。您希望在这里放置多个 SUB_TABLES 结构是您的问题,而不是语言的问题。在我看来,您唯一真正的选择是将 SUB_TABLES 更改为正确的指针,而不是大小不正确的数组。
  • @mah,C 确实提供了灵活的数组成员,这可能是 OP 所追求的。该标准没有使用术语“可变大小”来描述structs 拥有这样的成员,但这并不是不合理的俗语。然而,仔细观察,我认为灵活的数组成员不太合适。
  • @JohnBollinger C 中是否存在无法确定大小的内容?在这种情况下,我并不是说结构/数组的定义有什么问题,虽然这是一个有点模糊的模式,但它绝对是一个有其位置的模式。也就是说,该语言不支持它,因此按照 OP 想要的方式嵌套它对于这种模式无效。
  • @mah,不完全是。有关灵活数组成员的描述,请参见 C99 第 6.7.2.1 节第 16 节。这不是 OP 所具有的,但它看起来类似于在 C99 之前用于相同效果的(非标准)形式。
  • @JohnBollinger 我不知道这方面的语言规范部分,但gcc.gnu.org/onlinedocs/gcc/Zero-Length.html 声明 包含灵活数组成员的结构,或包含此类结构的联合(可能是递归的),可能不是结构的成员或数组的元素(尽管它还声明有 gcc 扩展允许它工作)。我猜你担心的是我关于不存在可变大小结构之类的说法——这种说法并不完全正确(但从事物的精神来看,也许也不完全不正确?)

标签: c struct


【解决方案1】:

首先,将指针作为整数值传递是一种不好的形式。如果您想避免命名特定类型,请使用 void *,但如果您总是要强制转换为特定指针类型,那么您应该将参数声明为具有该类型。

更重要的是,您似乎正在使用现在称为struct 的灵活数组成员的非标准形式。当您使用大于 1 的 count 访问 masterTable-&gt;subTables[count] 时,您的代码表现出未定义的行为。在 C99 中标准化的类似形式(它为更多 count 值定义了行为)将要求您声明 struct Master_table 有点不同:

struct Master_table
{
    uint Total_MasterTable_Length;
    struct SUB_TABLES subTables[];  /* no declared size */
}

通常的用法是为这些对象动态分配内存,足够固定大小的部分加上灵活数组所需的许多元素。然后允许通过灵活数组成员访问分配的空间,前提是您不访问超过为其分配的空间。

但是,您的代码注释指出,通过将索引递增到 Master_table.subTables 来访问连续子表是不正确的,如果正确,这似乎表明从地址 address 开始的数据实际上并不构成struct Master_table(如您所声明的),灵活的成员与否。

数组是固定大小对象的序列。您的 struct SUB_TABLES 是有效的数组元素类型,但它不是可变大小。由于它只有一个成员,因此它是该成员(联合)的大小,联合是其最大成员的大小。每个struct SUB_TABLES 对象都是那个大小。

如果您实际拥有的子表是 structs 的序列,类型为 struct subTable1 - struct subTable4,没有间隙,并且这些子表的大小不同,那么 不是 struct SUB_TABLES 的数组。此外,如果你只有你提供的数据,我看不出你怎么能在运行时弄清楚它是什么。

如果您的子表数据严格采用 {table_length,char[table_length]} 形式,那么您应该将 subTables 声明为 void *。您将需要使用强制转换和指针算法来处理数据。您或许可以使用带有灵活成员的子表 struct 类型来提供帮助,但将 subTables 声明为此类数组不会产生有用的效果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-24
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多