Home > Software design >  how to create a nested structure in c like in the body of the query?
how to create a nested structure in c like in the body of the query?

Time:06-20

//Contains the solution taking all answers to consideration.

typedef struct{
        struct address{
                int row0[10], row1[5];
        } addr;
        int * map[2];
}registers;

registers new_reg() {
    registers r = { { {0}, {0} }, {r.addr.row0, r.addr.row1} };
    return r;
}
int main() {
    registers reg = new_reg();
    reg.map[0][0] = 5;
    printf("%d\n", reg.map[0][0]);
    return 0;
}

//Contains the solution taking all answers to consideration.

CodePudding user response:

struct reg {
    struct address {
        int row0[10];
        int row1[5];
    } addr;
    int *i[2];
};

int main(void) {
    struct reg r;
    r.i[0] = r.addr.row0;
    r.i[1] = r.addr.row1;
    r.i[0][0] = 1;
    printf("%d\n", r.i[0][0]);
    return 0;
}

You can alternatively create an initialization function:

void reg_init (struct reg *pr) {
    pr->i[0] = pr->addr.row0;
    pr->i[1] = pr->addr.row1;
}

and then call reg_init (& r) every time after you define a new object of type struct reg. Then your new main function would be:

int main(void) {
    struct reg r;
    reg_init (& r);
    r.i[0][0] = 1;
    printf("%d\n", r.i[0][0]);
    return 0;
}

EDIT: If you want to have a dynamic number of rows, you could declare

struct reg {
    struct address {
        int row[N][MAX_NUMBER];
    } addr;
    int *i[N];
};

and have a loop in the init function.

CodePudding user response:

"something similar" is not particularly descriptive, and you almost certainly do not want to do this, but you can do:

#include <stdlib.h>
#include <stdio.h>

struct reg{
        struct address{
                int row0[10], row1[5];
        } addr;
        int * i[2];
};

int
main(void)
{
        struct reg r = { { {0}, {0} }, {r.addr.row0, r.addr.row1} };
        r.i[0][0] = 1;
        printf("%d\n", r.i[0][0]);
        return 0;
}

Some compilers even allow you to write:

struct reg r = { .i = {r.addr.row0, r.addr.row1} };

CodePudding user response:

Alternatively, you can specify a union that aliases r.addr.row0[0] with r.i[0] -- they are actually the same address in memory, just called by a different name.

#include <stdio.h>

union reg {
    struct {
        int row0[10], row1[5];
    } addr;
    int i[15];
};

int main(void) {
    union reg r;
    r.i[0] = 1;
    r.i[10] = 42;
    printf("%d -- %d\n", r.i[0], r.addr.row0[0]);
    printf("%d -- %d\n", r.i[10], r.addr.row1[0]);
    return 0;
}

Outputs,

1 -- 1
42 -- 42

It does this by overlaying the elements of the union, instead of the struct which assigns unique addresses to all it's members.

CodePudding user response:

So, a couple of issues.

You cannot have an initializer in a struct type definition; you must create an instance of the type and initialize members in that instance:

struct reg {
  struct address {
    int row0[10];
    int row1[5];
  } addr;
  int *i[2]; // we’ll talk about this later
};
...
struct reg r = // create an instance of struct reg
{
  {
    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, // row0
    { 0, 1, 2, 3, 4 } // row1
  }, 
  { 
    r.addr.row0, r.addr.row1 // i
  }
};

Secondly, if you want i to be an actual flexible array member with no fixed size, then you have to dynamically allocate the object with enough extra space for the number of elements, otherwise it won’t be allocated in the object. In other words, if your type definition is

struct reg {
  struct address {
    int row0[10];
    int row1[5];
  } addr;
  int *i[];
};

and you declare a variable as

struct reg r = { ... };

then the i member will not exist at all - if you try to add an initializer for the i member like I did above, the compiler will yell at you.

You would need to allocate an instance dynamically for the i member to exist, and only if you allocate extra memory for those array elements:

struct reg *r = malloc( sizeof *r   2 * sizeof (int *) );

And then you would to assign members individually:

r->row0[0] = 0;
r->row0[1] = 1;
...
r->row1[0] = 0;
r->row1[1] = 1;
...
r->i[0] = r->row0;
r->i[1] = r->row1;

So after writing all of that, I saw your conversation with Neil; what you’re looking at is

union reg {
    struct address {
      int row0[10];
      int row1[5];
    } addr;
    int i[15];
};

union reg r = { .i = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, } };

or

union reg r = { 
  .addr = { 
    .row0 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
    .row1 = { 10, 11, 12, 13, 14 }
  }
}; 

either way should work.

Here's a dump of the memory map, showing the whole union object, then the i member, then the addr member, and then each of the row0 and row1 members - you can see that r.i and r.addr have the same size and starting address (which is the same as the starting address of the entire union object). Similarly, r.addr.row0 starts at that same address:

       Item         Address   00   01   02   03
       ----         -------   --   --   --   --
          r     0x16b0377b0   00   00   00   00    ....
                0x16b0377b4   01   00   00   00    ....
                0x16b0377b8   02   00   00   00    ....
                0x16b0377bc   03   00   00   00    ....
                0x16b0377c0   04   00   00   00    ....
                0x16b0377c4   05   00   00   00    ....
                0x16b0377c8   06   00   00   00    ....
                0x16b0377cc   07   00   00   00    ....
                0x16b0377d0   08   00   00   00    ....
                0x16b0377d4   09   00   00   00    ....
                0x16b0377d8   0a   00   00   00    ....
                0x16b0377dc   0b   00   00   00    ....
                0x16b0377e0   0c   00   00   00    ....
                0x16b0377e4   0d   00   00   00    ....
                0x16b0377e8   0e   00   00   00    ....

        r.i     0x16b0377b0   00   00   00   00    ....
                0x16b0377b4   01   00   00   00    ....
                0x16b0377b8   02   00   00   00    ....
                0x16b0377bc   03   00   00   00    ....
                0x16b0377c0   04   00   00   00    ....
                0x16b0377c4   05   00   00   00    ....
                0x16b0377c8   06   00   00   00    ....
                0x16b0377cc   07   00   00   00    ....
                0x16b0377d0   08   00   00   00    ....
                0x16b0377d4   09   00   00   00    ....
                0x16b0377d8   0a   00   00   00    ....
                0x16b0377dc   0b   00   00   00    ....
                0x16b0377e0   0c   00   00   00    ....
                0x16b0377e4   0d   00   00   00    ....
                0x16b0377e8   0e   00   00   00    ....

     r.addr     0x16b0377b0   00   00   00   00    ....
                0x16b0377b4   01   00   00   00    ....
                0x16b0377b8   02   00   00   00    ....
                0x16b0377bc   03   00   00   00    ....
                0x16b0377c0   04   00   00   00    ....
                0x16b0377c4   05   00   00   00    ....
                0x16b0377c8   06   00   00   00    ....
                0x16b0377cc   07   00   00   00    ....
                0x16b0377d0   08   00   00   00    ....
                0x16b0377d4   09   00   00   00    ....
                0x16b0377d8   0a   00   00   00    ....
                0x16b0377dc   0b   00   00   00    ....
                0x16b0377e0   0c   00   00   00    ....
                0x16b0377e4   0d   00   00   00    ....
                0x16b0377e8   0e   00   00   00    ....

r.addr.row0     0x16b0377b0   00   00   00   00    ....
                0x16b0377b4   01   00   00   00    ....
                0x16b0377b8   02   00   00   00    ....
                0x16b0377bc   03   00   00   00    ....
                0x16b0377c0   04   00   00   00    ....
                0x16b0377c4   05   00   00   00    ....
                0x16b0377c8   06   00   00   00    ....
                0x16b0377cc   07   00   00   00    ....
                0x16b0377d0   08   00   00   00    ....
                0x16b0377d4   09   00   00   00    ....

r.addr.row1     0x16b0377d8   0a   00   00   00    ....
                0x16b0377dc   0b   00   00   00    ....
                0x16b0377e0   0c   00   00   00    ....
                0x16b0377e4   0d   00   00   00    ....
                0x16b0377e8   0e   00   00   00    ....
  • Related