Reputation: 444
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.
Upvotes: 1
Views: 823
Reputation: 134416
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.
Upvotes: 1
Reputation: 68099
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},
};
Upvotes: 0
Reputation: 37327
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.
Upvotes: 6