In C I can initialize an array on the stack like so:
SOME_DATA_TYPE* x = (SOME_DATA_TYPE[5]) {v1, v2, v3, v4, v5};
Is there a similar one-line method to assign values to a malloc()
-ed array on the heap?
SOME_DATA_TYPE* y = malloc(sizeof(SOME_DATA_TYPE)*5);
// what comes here?
Or do I have to iterate over the array and assign values individually?
The first issue about "initializing" the result of malloc()
is that the allocation may fail. Here y
is initialized to some pointer value. The data referenced is still indeterminate.
#define element_count 5
SOME_DATA_TYPE *y = malloc(sizeof *y * element_count);
if (y == NULL) Handle_OutOfMemory();
With C11, code can use compound literals to set, not initialize, the data pointed to by y
.
memcpy(y, (SOME_DATA_TYPE[element_count]) {v1, v2, v3, v4, v5}, sizeof *y * element_count);
Using a direct one-liner without checking the allocation would not be robust programming.
// one-liner, but not robust code
SOME_DATA_TYPE *y = memcpy(malloc(sizeof *y * element_count),
(SOME_DATA_TYPE[element_count]) {v1, v2, v3, v4, v5}, sizeof *y * element_count);
Notice code uses the sizeof *pointer_variable * element_count
rather than sizeof (pointer_variable_dereferenced_type) * element_count
as easier to code, less error prone, easier to review and maintain. Either approach will work.
You could define a function like so:
#include <stdarg.h>
#include <stdlib.h>
int * intMallocInit (int length, ...) {
// Initialize Variable Arguments
va_list args;
va_start (args, length);
// Allocate Memory
int * arr = malloc (sizeof(int) * length);
if (arr == NULL) return NULL;
// Initialize Array
for (int i = 0; i < length; i++) {
arr[i] = va_arg(args, int);
}
// Clean Up and Return
va_end(args)
return arr;
}
And we could call it like so:
int len = 3;
int * myArray = intMallocInit (len, 4, 5, 2);
if (myArray == NULL) return 0;
for (int i = 0; i < len; i++) {
printf("%d,", myArray [i]);
}
Output: 4,5,2,
Note: We could also define floatMallocInit (), etc. simply by replacing every instance of "int" in the above function to "float"
You could also use void pointers, or enum& switch, but I wont go there.
Untested attempt at general function Im sure theres a clever work around fhe switchs but this is what I can come up with.
#include <stdarg.h>
#include <stdlib.h>
enum {INT, FLOAT /* etc...*/}
int getSize(int type) {
int typeSize = 0;
switch (type) {
case INT:
typeSize = sizeof (int);
break;
case FLOAT:
typeSize = sizeof (float);
break;
// Etc...
default:
return -1;
}
return typeSize;
}
void * mallocInit (int type, int length, ...) {
// Initialize Variable Arguments
va_list args;
va_start (args, length);
// Get Size of type
int typeSize = getSize(type);
if (typeSize == -1) return NULL;
// Allocate Memory
void * arr = malloc (typeSize * length);
if (arr == NULL) return NULL;
// Initialize Array, Maybe va_copy can be used? No good reference
for (int i = 0; i < length; i++) {
switch(type) {
case INT:
arr[i] = va_args(args, int);
break;
// Etc..
}
}
// Clean Up and Return
va_end(args)
return arr;
}
Called with
float myArray = mallocInit (FLOAT, 3, 1, 5, 7);
One way to do it without getting too far away from the natural C memory management philosophy, is to use a memdup
-like function. Since it is not standard, you might have to implement it yourself
SOME_DATA_TYPE *y = memdup(
(SOME_DATA_TYPE[5]) {v1, v2, v3, v4, v5},
5 * sizeof(SOME_DATA_TYPE));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With