简体   繁体   中英

Variable sized structures within another variable sized structure

I have variable sized structures within a variable structure. What is a good way to walk each sub table? The buffer is byte-packed and is available at 'address'. No need to malloc. Cannot do indexing in while loop, Is offsetting with table sizes is the only option?


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];
}

In the first place, it's bad form to pass pointers as integer values. Use a void * if you want to avoid naming a specific type, but if you're always going to cast to a specific pointer type then you should just declare the argument to have that type.

More to the point, you appear to be using a non-standard form of what is now known as a flexible array member of your struct . Your code exhibits undefined behavior when you access masterTable->subTables[count] with count larger than 1. The similar form standardized in C99 (which has defined behavior for more values of count ) would require you to declare struct Master_table a bit differently:

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

The usual usage is to dynamically allocate memory for such objects, enough for the fixed-size part plus however many elements you need of the flexible array. It is then permitted to access the allocated space via the flexible array member, provided that you do not access past the space allocated for it.

However, your code comment that it is incorrect to access successive subtables by incrementing an index into Master_table.subTables , if correct, seems to indicate that data starting at address address do not, in fact, constitute a valid representation of a struct Master_table (as you have declared it), flexible member or not.

Arrays are sequences of fixed-size objects. Your struct SUB_TABLES is a valid array element type, but it is not variable-size. Since it has only one member, it is the size of that member (a union), and the union is the size of its largest member. Every struct SUB_TABLES object is that size.

If what you actually have for subtables is a sequence of struct s variously of types struct subTable1 - struct subTable4 , packed without gaps, and those subtables are of different sizes, then that is not an array of struct SUB_TABLES . Moreover, I don't see how you can figure out what it is even at runtime if you have only the data you present.

If your subtable data are strictly of the form { table_length , char[table_length] }, then you should declare subTables as a void * . You will need to use casts and pointer arithmetic to work your way through the data. You could perhaps use a subtable struct type with a flexible member to help, but declaring subTables as an array of such would not have a useful effect.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM