1

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.

Cewein
  • 396
  • 2
  • 14
  • Possible duplicate of [Initialize values of array in a struct](https://stackoverflow.com/questions/9856045/initialize-values-of-array-in-a-struct) – static_cast Dec 21 '18 at 13:53
  • @static_cast not fully a dubplicate because i want also to acces the var after creating it, seem like the only option i've found it doing array[0], array[1], ect.. – Cewein Dec 22 '18 at 21:06

3 Answers3

6

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.

iBug
  • 35,554
  • 7
  • 89
  • 134
1

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.

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

P.P.S.

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.

Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
0

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},   
};
0___________
  • 60,014
  • 4
  • 34
  • 74