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);