Assign multiple values to array in C

Viewed 129605

Is there any way to do this in a condensed form?

GLfloat coordinates[8];
...
coordinates[0] = 1.0f;
coordinates[1] = 0.0f;
coordinates[2] = 1.0f;
coordinates[3] = 1.0f;
coordinates[4] = 0.0f;
coordinates[5] = 1.0f;
coordinates[6] = 0.0f;
coordinates[7] = 0.0f;
return coordinates;

Something like coordinates = {1.0f, ...};?

8 Answers

I went with an array initialization method:

#include <stdarg.h>

void int_array_init(int *a, const int ct, ...) {
  va_list args;
  va_start(args, ct);
  for(int i = 0; i < ct; ++i) {
    a[i] = va_arg(args, int);
  }
  va_end(args);
}

called like,

const int node_ct = 8;
int expected[node_ct];
int_array_init(expected, node_ct, 1, 3, 4, 2, 5, 6, 7, 8);

The C99 array initialization, like this:

const int node_ct = 8;
const int expected[node_ct] = { 1, 3, 4, 2, 5, 6, 7, 8 };

And in the configure.ac:

AC_PROG_CC_C99

had the compiler on my dev box perfectly happy. The compiler on the server complained with:

error: variable-sized object may not be initialized
   const int expected[node_ct] = { 1, 3, 4, 2, 5, 6, 7, 8 };

and

warning: excess elements in array initializer
   const int expected[node_ct] = { 1, 3, 4, 2, 5, 6, 7, 8 };

for each element

It doesn't complain at all about, for example:

int expected[] = { 1, 2, 3, 4, 5 };

I like the check on size, and that the varargs support is acting more robustly than the support for the array initializer.

Find PR with sample code at https://github.com/wbreeze/davenport/pull/15/files

Regarding https://stackoverflow.com/a/3535455/608359 from @paxdiablo, I liked it; but, felt insecure about having the number of times the initializaion pointer advances synchronized with the number of elements allocated to the array. Worst case, the initializing pointer moves beyond the allocated length. As such, the diff in the PR contains,

  int expected[node_ct];
- int *p = expected;
- *p++ = 1; *p++ = 2; *p++ = 3; *p++ = 4;
+ int_array_init(expected, node_ct, 1, 2, 3, 4);

The int_array_init method will safely assign junk if the number of arguments is fewer than the node_ct. The junk assignment ought to be easier to catch and debug.

If you are doing these same assignments a lot in your program and want a shortcut, the most straightforward solution might be to just add a function

static inline void set_coordinates(
        GLfloat coordinates[static 8],
        GLfloat c0, GLfloat c1, GLfloat c2, GLfloat c3,
        GLfloat c4, GLfloat c5, GLfloat c6, GLfloat c7)
{
    coordinates[0] = c0;
    coordinates[1] = c1;
    coordinates[2] = c2;
    coordinates[3] = c3;
    coordinates[4] = c4;
    coordinates[5] = c5;
    coordinates[6] = c6;
    coordinates[7] = c7;
}

and then simply call

GLfloat coordinates[8];
// ...
set_coordinates(coordinates, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f);
typedef struct{
  char array[4];
}my_array;

my_array array = { .array = {1,1,1,1} }; // initialisation

void assign(my_array a)
{
  array.array[0] = a.array[0];
  array.array[1] = a.array[1];
  array.array[2] = a.array[2];
  array.array[3] = a.array[3]; 
}

char num = 5;
char ber = 6;

int main(void)
{
  printf("%d\n", array.array[0]);
// ...

  // this works even after initialisation
  assign((my_array){ .array = {num,ber,num,ber} });

  printf("%d\n", array.array[0]);
// ....
  return 0;
}
Related