简体   繁体   中英

Initializing typedef arrays in structs

I'm making a Camera struct. the struct use a vec3 which is defined with typedef float vec3[3] .

To initialize a vec3 I do vec3 vector = {0.,0.,0.};

My Cameras struct is like this:

typedef struct Cameras {
    vec3 eye;
    vec3 target
} Camera;

but when I do:

Camera cam;
cam.eye = { .5, 1., 0. };

it crashes and the compiler tells me: expression must be modifiable .

I thought it was an error with pointer but no, and replacing vec3 eye to vec3 * eye and cam->eye = {.5,1.,0.} changes nothing.

Am I creating the struct the wrong way or is a really common issue C and I'm just blind?

here my goal is not only to initalise the array, but also accessing the data and modifing/passing into function after the creation.

It's because after the line cam is defined, subsequent "assignments" are no longer initializations .

To initialize an instance, you must put the "assignment" at the same place where it's defined:

Camera cam = { {.5, 1., 0.} };

or specifying member:

Camera cam = { .eye = {.5, 1., 0.} };

Note that this will also automatically zero-initialize cam.target as no initial values are specified for it.

The error you get is obvious, type of vec3 is float [3] - array type and you certainly cannot "assign" to array types.

You can use the initialization as mentioned by iBug in another answer. However, with a small trick , you'll be able to use the assignment, also. This would need the usage of a pointer and compound literal .

You need to change the typedef to vec3

 typedef float* vec3;

so as to make it a float * and then, you can use compound literal to assign the values, like

cam.eye = (float [3]){ .5, 1., 0. };
cam.target = (float [3]){ .45, 2.5, 0.9 }; // just some other values.

The primary benefit of using this approach is, you are not limited to only "initialization", you can perform the assignment at any time.

PS - Compound literals are modifiable , so you do not lose any operation capabilities.

PPS

Quoting C11 , chapter §6.5.2.5/ P12

 "/tmp/fileXXXXXX" (char []){"/tmp/fileXXXXXX"} (const char []){"/tmp/fileXXXXXX"} 

The first always has static storage duration and has type array of char, but need not be modifiable; the last two have automatic storage duration when they occur within the body of a function, and the first of these two is modifiable.

I personally prefer more "descriptive" initialization - I like members to be specified - the code is easier to read for humans.

typedef float vec3[3];

typedef struct Cameras {
    vec3 eye;
    vec3 target;
} Camera;

Camera c = 
{
  .eye = {1.0, 2.0, 3.0},   
  .target = {4.0, 5.0, 6.0},   
};

Camera c1 = 
{
  .target = {4.0, 5.0, 6.0},   
};

Camera c2 = 
{
  .eye = {1.0, 2.0, 3.0},   
};

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