In a project I'm working on, I find myself creating a lot of small, hand-written arrays of structs that need to be stored in dynamically allocated memory (mostly for testing with small datasets before importing from a file). There's a really nice syntax to initialize a static array of structs, as vec2 below, but I've been using the solution vec3 below that uses memcpy.
vec4 shows sort of what I'd like to be able to do, but obviously it doesn't quite work. Even though the anonymous array *((struct vec2d[]) { {1, 2}, {3, 4}, {5, 6} }) contains three strut vec2ds, when it (and the LHS) are dereferenced, they become (struct vec2d), so only the first struct vec2d gets assigned to the memory allocated at vec4.
Is there some way for me to accomplish this purely as an assignment, without using memcpy?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct vec2d
{
double x,y;
};
//void print_vec2d(char *, struct vec2d *);
void print_vec2ds(char *label, size_t count, struct vec2d *vec)
{
for (size_t i = 0; i < count; i++)
{
printf("%s (%li of %li): (%f, %f)\n", label, i + 1, count, (vec[i]).x, (vec[i]).y);
}
printf("\n");
}
int
main(int c, char **a)
{
// nice and concise syntax
struct vec2d vec2[3] =
{
{12, 34},
{56, 78},
{90, 112}
};
print_vec2ds("vec2", 3, vec2);
// a little bulky to have to wrap it all in a call to memcpy
struct vec2d *vec3 = calloc(3, sizeof(struct vec2d));
memcpy(vec3, (struct vec2d[])
{
{1, 2},
{3, 4},
{5, 6}
}, 3*sizeof(struct vec2d));
print_vec2ds("vec3", 3, vec3);
// this doesn't (and shouldn't) work, but I like the syntax :)
struct vec2d *vec4 = calloc(3, sizeof(struct vec2d));
*vec4 = *((struct vec2d[])
{
{1, 2},
{3, 4},
{5, 6}
});
print_vec2ds("vec4", 3, vec4);
}
program output, showing how last assignment doesn't work:
vec2 (1 of 3): (12.000000, 34.000000)
vec2 (2 of 3): (56.000000, 78.000000)
vec2 (3 of 3): (90.000000, 112.000000)
vec3 (1 of 3): (1.000000, 2.000000)
vec3 (2 of 3): (3.000000, 4.000000)
vec3 (3 of 3): (5.000000, 6.000000)
vec4 (1 of 3): (1.000000, 2.000000)
vec4 (2 of 3): (0.000000, 0.000000)
vec4 (3 of 3): (0.000000, 0.000000)
Incidentally, I discovered that it's possible to cast the LHS and RHS of the assignment into the pointer type of a struct which holds the amount of data I want to assign:
struct bad {double a,b,c,d,e,f};
struct vec2d *vec5 = calloc(3, sizeof(struct vec2d));
*((struct bad*) vec5) = *((struct bad*) ((struct vec2d[])
{
{1, 2},
{3, 4},
{5, 6}
}));
print_vec2ds("vec5", 3, vec5);
which "works", but it requires a struct of the precise length to be defined, which isn't really a solution…
structwith 3struct vec2dmakes more sense than astructwith 6double. Why introduce a new 6doubleone?