There are 2 basic approaches to accomplish what you are attempting: one with and one without using a flexible array member. Your posted code is half of one way and half the other, so the pieces aren't working together.
A version of the FAM approach would be:
#include <stdlib.h>
#include <string.h>
typedef struct Vector2D {
float x, y;
} Vector2D;
typedef struct Shape {
int n;
Vector2D vertices[]; // FAM
} Shape;
Shape *create_square(float side_length) {
// Define vertices
Vector2D vertices[4] = {
{0, 0},
{0, side_length},
{side_length, side_length},
{side_length, 0}
};
//one malloc to include everything
Shape *shape = malloc(sizeof(Shape) + 4 * sizeof(Vector2D));
shape->n = 4;
memcpy( shape->vertices, vertices, sizeof(vertices) );
return shape;
}
A version of the non-FAM approach that also produces a dynamically allocated Shape (as suggested by @John Bollinger) would be:
#include <stdlib.h>
#include <string.h>
typedef struct Vector2D {
float x, y;
} Vector2D;
typedef struct Shape {
int n;
Vector2D *vertices;
} Shape;
Shape *create_square(float side_length) {
// Define vertices
Vector2D vertices[4] = {
{0, 0},
{0, side_length},
{side_length, side_length},
{side_length, 0}
};
// one malloc for the base shape and
// a second one for the array pointed to by a member
Shape *shape = malloc( sizeof(Shape) );
shape->n = 4;
shape->vertices = malloc( 4 * sizeof(Vector2D));
memcpy( shape->vertices, vertices, sizeof(vertices) );
return shape;
}
Another version of the non-FAM approach which doesn't produce a dynamically allocated shape (as part of your posted code appears to attempt) would be:
#include <stdlib.h>
#include <string.h>
typedef struct Vector2D {
float x, y;
} Vector2D;
typedef struct Shape {
int n;
Vector2D *vertices;
} Shape;
Shape create_square(float side_length) {
// Define vertices
Vector2D vertices[4] = {
{0, 0},
{0, side_length},
{side_length, side_length},
{side_length, 0}
};
// one malloc for the array pointed to by a member
// shape is a local variable that can go out of scope,
// but can also be passed or returned by value rather than via pointer
Shape shape;
shape.n = 4;
shape.vertices = malloc( 4 * sizeof(Vector2D));
memcpy( shape.vertices, vertices, sizeof(vertices) );
return shape;
}
In all cases you also would have to provide for releasing the dynamically allocated memory when you are done with it.
Other versions are possible and may have different usage characteristics.
Notable issues with using a FAM is that they must be dynamically allocated and you cannot create arrays of them. (arrays of pointers to them will work.)
shape->vertices = vertices;points the pointer to a local variable which will go out of scope when the function exits.shape->vertices = vertices;sets a pointer to the address of a local variable (array) that vanishes when the function exits... You've malloced space, but you need to fill that space... (PS: malloc can return NULL...)Vector2D vertices[];instead ofVector2D *vertices;. And those you would be able to set viashape->vertices[i].xandshape->vertices[i].y, but not via an initializer.