1

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…

9
  • Are the array sizes and values typically hard coded in practice? Commented Feb 27, 2022 at 1:39
  • FYI, the RHS is called a "compound literal". Commented Feb 27, 2022 at 1:42
  • In C, (almost) anything is possible. Commented Feb 27, 2022 at 1:55
  • The only way you'll be able copy an array by assignment is by embedding the array in a structure (because that makes the array size explicit in all contexts). Commented Feb 27, 2022 at 2:04
  • 1
    A struct with 3 struct vec2d makes more sense than a struct with 6 double. Why introduce a new 6 double one? Commented Feb 27, 2022 at 5:58

1 Answer 1

3

Is there some way for me to accomplish this purely as an assignment, without using memcpy?

I believe that the size needs to be known at compile-time in order to do a pure assignment. Otherwise memcpy() is a fine solution. If you want to make it a bit simpler you could maybe do something like:

  struct vec2d vec2[3] =
  {
    {12, 34},
    {56, 78},
    {90, 112}
  };

  struct vec2d *vec3 = malloc(sizeof(vec2));
  memcpy(vec3, vec2, sizeof(vec2));
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.