part of c programming
sometimes it would be useful to assign array content literally by listing the contents. something like this is possible in most scripting languages:
a = [1, 2, 3, 4]
but c is limited and the following shows some possible options and alternatives.
int a[] = {1, 2, 3};
int a[3][2] = {{1, 2}, {3, 4}, {5, 6}};
more information:
int *a = (int[]){1, 2, 3, 4};
void print_array(int *arr, size_t size); print_array((int[]){1, 2, 3, 4}, 4);
int *a = malloc(4 * sizeof(int)); if (!a) exit(1); memcpy(a, (int[]){1, 2, 3, 4}, 4 * sizeof(int));
static inline int *new_array(size_t size, int values[]) { int *a = malloc(size * sizeof(int)); if (a) memcpy(a, values, size * sizeof(int)); return a; } int *a = new_array(4, (int[]){1, 2, 3, 4});
typedef struct int_array3 { int data[3]; } int_array3_t; int_array3_t x = {.data = {1, 2, 3}};
x.data[1] int_array3_t y = x;
this is aggregate initialization with the added benefit that the whole array can be used like a scalar value.
since c99, the last member of a struct can be an array of unspecified size.
typedef struct { size_t size; int data[]; } int_array_t;
however, to make use of this, the struct has to be allocated on the heap. since it is only accessible via a pointer, the resulting struct can not be copied like a scalar value.
functions that return heap arrays.
#include <stdlib.h> int* int_array4(int a, int b, int c, int d) { int* x = malloc(4 * sizeof(int)); if (!x) return 0; x[0] = a; x[1] = b; x[2] = c; x[3] = d; return x; }
int* e = int_array4(2, 3, 4, 5);
this can also be used with a variable number of arguments.
#include <stdarg.h> int *new_array(size_t n, ...) { int *a = malloc(n * sizeof(int)); if (!a) return 0; va_list args; va_start(args, n); for (size_t i = 0; i < n; i += 1) { a[i] = va_arg(args, int); } va_end(args); return a; } int *a = new_array(4, 1, 2, 3, 4);
memory allocation can fail, therefore the question of how to handle this failure arises.
this is similar to malloc, which also just returns a null pointer on failure. this has to be checked to avoid null pointer access
no further error-checking code is needed, nor relevant, with this option. however, this option doesnt compose well, as it exits the calling process - a behavior that is particularly undesirable when the code is used within a library.
example, inside the array creating function:
if (!x) exit(1);
#define array_set4(x, a, b, c, d) x[0] = a; x[1] = b; x[2] = c; x[3] = d;
#include <stdlib.h> int* x = malloc(4 * sizeof(int)); if (!x) exit(1); array_set4(x, 2, 3, 4, 5);
this allows setting any number of elements.
#define new_array(...) ((int[]){__VA_ARGS__}) int *a = new_array(1, 2, 3, 4);
#define new_array(size, ...) ({ \ int* _arr = malloc(size * sizeof(int)); \ if (_arr) { \ int _tmp[] = {__VA_ARGS__}; \ memcpy(_arr, _tmp, size * sizeof(int));\ } \ _arr; \ }) int *a = new_array(4, 1, 2, 3, 4);