//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 ....