I used malloc to define an index because each line had a different number of elements (simplified example below):
int** Index=malloc(2*sizeof(int*));
Index[0]=malloc(2*sizeof(int));
Index[1]=malloc(3*sizeof(int));
But I did not want to write each element one by one (as follows) because it takes a lot of space and time:
Index[0][0]=1000;
Index[0][1]=1300;
Index[1][0]=1500;
Index[1][1]=2000;
Index[1][2]=2900;
But rather wanted to use a way to do it in a single line of code as follows:
Index[0]={1000,1300};
Index[1]={1500,2000,2900};
As I've been taught to do on "regular" indexes. Only problem is that my compiler doesn't seem to like such notations with an index defined with the help of a malloc. Is there another way rather than to write dozens of lines of code?
I searched for a similar question on this website but was unable to find one.
You can't assign to an array with an initializer list but you can copy whole arrays if you place them in structs and since the sizes are hardcoded 2 and 3, you could put both arrays in a struct that you initialize with an initializer list and then use compound literal assignment to the dynamically allocted struct.
Example:
#include <stdlib.h>
struct Indices {
int a[2];
int b[3];
};
int main() {
struct Indices* Index = malloc(sizeof *Index);
*Index = (struct Indices){ // compound literal assignment
{1000, 1300},
{1500, 2000, 2900}
};
free(Index);
}
You can also use designated initializers if you want to make it even clearer:
*Index = (struct Indices){
.a = {1000, 1300},
.b = {1500, 2000, 2900}
};
If you for example still would like to access both your arrays via index, you could simply put the pointers to the first elements in a temporary array.
Iterating over this will probably (not measured) be more efficient than having the arrays potentially allocated in such a way that cache locality goes out the window.
Example:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#define SIZE(x) (sizeof(x) / sizeof *(x))
enum : size_t { Asize = 2, Bsize = 3 };
constexpr size_t Sizes[] = {Asize, Bsize};
struct Indices {
int a[Asize];
int b[Bsize];
};
int main() {
struct Indices* Index = malloc(sizeof *Index);
*Index = (struct Indices){ // compound literal assignment
{1000, 1300},
{1500, 2000, 2900},
};
int* arrs[] = {Index->a, Index->b};
for (size_t i = 0; i != SIZE(arrs); ++i) {
for (size_t j = 0, end = Sizes[i]; j != end; ++j) {
printf("%zu,%zu = %d\t", i, j, arrs[i][j]);
// ^^^^^^^^^^
}
putchar('\n');
}
free(Index);
}
Demo
If you want to initialize the content of a dynamically allocated memory block with the content of an array containing hardcoded values, then I suggest that you declare a static constexpr array containing these values, and then copy these values into the dynamically allocated array using memcpy.
Using static constexpr has the advantage that the array with the source data will be put into the read-only data section of the executable, so that it does not have to be created every time you need it.
If you are using a compiler that does not yet support C23, you can use static const instead of static constexpr.
When creating the arrays with the source data, you can use the desired array initialization syntax.
Here is an example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void my_func()
{
// declare the source arrays
static constexpr int source_array_0[] = { 1000, 1300 };
static constexpr int source_array_1[] = { 1500, 2000, 2900 };
// calculate the number of elements in the source arrays
static constexpr int source_array_0_num_elements = sizeof source_array_0 / sizeof *source_array_0;
static constexpr int source_array_1_num_elements = sizeof source_array_1 / sizeof *source_array_1;
// allocate memory for the array of pointers
int **Index = malloc( 2 * sizeof *Index );
if ( Index == NULL )
{
fprintf( stderr, "Memory allocation failure!\n" );
exit( EXIT_FAILURE );
}
// allocate memory for the copies of the source arrays
Index[0] = malloc( sizeof source_array_0 );
Index[1] = malloc( sizeof source_array_1 );
if ( Index[0] == NULL || Index[1] == NULL )
{
fprintf( stderr, "Memory allocation failure!\n" );
exit( EXIT_FAILURE );
}
// initialize the content of the dynamically allocated arrays from the source arrays
memcpy( Index[0], source_array_0, sizeof source_array_0 );
memcpy( Index[1], source_array_1, sizeof source_array_1 );
// print the content of the dynamically allocated arrays, in order to verify that they
// were initialized properly
for ( int i = 0; i < source_array_0_num_elements; i++ )
{
printf( "%d\n", Index[0][i] );
}
printf( "\n" );
for ( int i = 0; i < source_array_1_num_elements; i++ )
{
printf( "%d\n", Index[1][i] );
}
// cleanup
free( Index[1] );
free( Index[0] );
free( Index );
}
Calling the function my_func above will print the following output:
1000
1300
1500
2000
2900
Here is a demonstration.
As you can see, the dynamically allocated arrays were correctly initialized with the hardcoded data from the source arrays.
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