Just compute the total amount of memory needed for both nrows row-pointers, and the actual data, add it all up, and do a single call:
int **array = malloc(nrows * sizeof *array + (nrows * (ncolumns * sizeof **array));
If you think this looks too complex, you can split it up and make it a bit self-documenting by naming the different terms of the size expression:
int **array; /* Declare this first so we can use it with sizeof. */
const size_t row_pointers_bytes = nrows * sizeof *array;
const size_t row_elements_bytes = ncolumns * sizeof **array;
array = malloc(row_pointers_bytes + nrows * row_elements_bytes);
You then need to go through and initialize the row pointers so that each row's pointer points at the first element for that particular row:
size_t i;
int * const data = array + nrows;
for(i = 0; i < nrows; i++)
array[i] = data + i * ncolumns;
Note that the resulting structure is subtly different from what you get if you do e.g. int array[nrows][ncolumns], because we have explicit row pointers, meaning that for an array allocated like this, there's no real requirement that all rows have the same number of columns.
It also means that an access like array[2][3] does something distinct from a similar-looking access into an actual 2d array. In this case, the innermost access happens first, and array[2] reads out a pointer from the 3rd element in array. That pointer is then treatet as the base of a (column) array, into which we index to get the fourth element.
In contrast, for something like
int array2[4][3];
which is a "packed" proper 2d array taking up just 12 integers' worth of space, an access like array[3][2] simply breaks down to adding an offset to the base address to get at the element.
Just compute the total amount of memory needed for both nrows row-pointers, and the actual data, add it all up, and do a single call:
int **array = malloc(nrows * sizeof *array + (nrows * (ncolumns * sizeof **array));
If you think this looks too complex, you can split it up and make it a bit self-documenting by naming the different terms of the size expression:
int **array; /* Declare this first so we can use it with sizeof. */
const size_t row_pointers_bytes = nrows * sizeof *array;
const size_t row_elements_bytes = ncolumns * sizeof **array;
array = malloc(row_pointers_bytes + nrows * row_elements_bytes);
You then need to go through and initialize the row pointers so that each row's pointer points at the first element for that particular row:
size_t i;
int * const data = array + nrows;
for(i = 0; i < nrows; i++)
array[i] = data + i * ncolumns;
Note that the resulting structure is subtly different from what you get if you do e.g. int array[nrows][ncolumns], because we have explicit row pointers, meaning that for an array allocated like this, there's no real requirement that all rows have the same number of columns.
It also means that an access like array[2][3] does something distinct from a similar-looking access into an actual 2d array. In this case, the innermost access happens first, and array[2] reads out a pointer from the 3rd element in array. That pointer is then treatet as the base of a (column) array, into which we index to get the fourth element.
In contrast, for something like
int array2[4][3];
which is a "packed" proper 2d array taking up just 12 integers' worth of space, an access like array[3][2] simply breaks down to adding an offset to the base address to get at the element.
int **array = malloc (nrows * sizeof(int *) + (nrows * (ncolumns * sizeof(int)));
This works because in C, arrays are just all the elements one after another as a bunch of bytes. There is no metadata or anything. malloc() does not know whether it is allocating for use as chars, ints or lines in an array.
Then, you have to initialize:
int *offs = &array[nrows]; /* same as int *offs = array + nrows; */
for (i = 0; i < nrows; i++, offs += ncolumns) {
array[i] = offs;
}
im having malloc problems with a double 2d array
Malloc a 2D array in C - Stack Overflow
How to cudaMalloc two-dimensional array ?
c - How to malloc 2D arrays? - Stack Overflow
Videos
the task is to use MPI in distributed memory to take average of 4 adjacent values in a (size x size) matrix, and the start/end/workload are areas worked out for each process to do the maths, then the edges of those areas are exchanged (note that top and bottom row are untouched calculation wise, but necessary to do other rows) this is repeated until a certain precision is met in the overall calculation I cant seem to figure out what to do with my array creation as it keeps giving me segmentation fault error (11), signal code (128) any help is appreciated, thank u in advance
this function takes
size (size of matrix, column in my case)
workload (the amount of lines each process will do maths)
start (starting position in the array)
end (end position in the array
the current inputs are:
size = 30
processes = 6 so the split work for a 30x30 array would be:
proc rank0 = workload = 5 (start = 1, end = 6)
proc rank1 = workload = 5 (start = 6, end = 11)
proc rank2 = workload = 5 (start = 11, end = 16)
proc rank3 = workload = 5 (start = 16, end = 21)
proc rank4 = workload = 4 (start = 21, end = 25)
proc rank5 = workload = 4 (start = 25, end = 29)
double** createArray(int size, int workload, int start, int end, int rank){
printf("\t rank:%d\n", rank);
printf("\t workload:%d", workload);
printf("\t start:%d", start);
printf("\t end:%d", end);
//declare array
//double **arr;
//memory is allocated for the matrix
double** arr = (double**) malloc(sizeof(double*)*(workload+2));
for (int i=0; i<size; i++){
arr[i] = malloc(sizeof(double)*size);
}
//writes the start vlaues into the matrix
//we need workload and extra edges each
for (int i=start-1; i<end+1; i++){
for (int j=0; j<size; j++){
//the upper and left rows are set to 1
if (i==0){
arr[i][j] = 1;
}
else if (j==0){
arr[i][j] = 1;
}
//other elements are set to 0
else{
arr[i][j] = 0;
}
}
printf("\n");
}
if(rank == 0){
for (int i=start-1; i<end+1; i++){
for (int j=0; j<end; j++){
printf("%lf", arr[i][j]);
}
printf("\n");
}
}
*/
//returns the array
return arr;}
like this : int (*arr)[M] = malloc(sizeof(int[N][M]));
arr is pointer to int[M].
use like arr[0][M-1];
and free(arr);
int ** arr = malloc(N*sizeof(int[M]));
is incorrect C code, if you simulate it by allocating once
int *arr = malloc(N*M*sizeof(int));
and access it by
arr[i*M + j],
this is an analog to arr[I][j] in your first case.
You say in the comments that n is the number of rows. So you need to allocate n rows each of length m. Therefore, the second for loop condition should be i < n. Also, you should check the return value of malloc for NULL in case it fails to allocate memory. I suggest the following change -
long long **a = malloc(n * sizeof(*a));
for (i = 0; i < n; i++) {
a[i] = malloc(m * sizeof(*a[i]));
}
Please note that a multi-dimensional array is not a fundamentally new type. It's simply an array of elements where each element itself is an array (for a 2D array), an array of arrays (for a 3D) array and so on. If you are using C99, you can allocate your array cleanly and succinctly as
int nrow = 4; // number of rows
int ncol = 8; // number of columns
// define arr to be a pointer to an array of ncol ints, i.e.,
// arr is a pointer to an object of type (int[ncol])
int (*arr)[ncol] = malloc(sizeof(int[nrow][ncol]));
// check the result of malloc for NULL
if (arr == NULL) {
printf("malloc failed to allocate memory\n");
// handle it
}
// do stuff with arr
for (int i = 0; i < nrow; i++) {
for (int j = 0; j < ncol; j++) {
arr[i][j] = i + j;
}
}
// after you are done with arr
free(arr);
You should also go through this - How do I work with dynamic multi-dimensional arrays in C?
You have three errors: The first is that you allocate only 5 secondary arrays, but in the input you loop over 6 of them.
The second problem is that array indices are zero-based, i.e. the index start at zero and goes to the size minus one.
The third problem is that you scan for two numbers (why?), but you provide only one destination pointer to scanf.
Numpy C API
Your question is similar to this post.
You can use the function below to pass a C pointer to Numpy array. The memory will be freed automatically when the Numpy array is recycled. If you want free the pointer mamully, you should not set NPY_OWNDATA flag.
import numpy as np
cimport numpy as np
cdef pointer_to_numpy_array_complex128(void * ptr, np.npy_intp size):
'''Convert c pointer to numpy array.
The memory will be freed as soon as the ndarray is deallocated.
'''
cdef extern from "numpy/arrayobject.h":
void PyArray_ENABLEFLAGS(np.ndarray arr, int flags)
cdef np.ndarray[np.complex128, ndim=1] arr = \
np.PyArray_SimpleNewFromData(1, &size, np.NPY_COMPLEX128, ptr)
PyArray_ENABLEFLAGS(arr, np.NPY_OWNDATA)
return arr
For reference:
- PyArray_SimpleNewFromData
- Numpy Data Type API
Cython Typed Memoryviews
Of couse, you can also use cython memoryview.
import numpy as np
cimport numpy as np
cdef np.complex128_t[:,:] view = <np.complex128_t[:n,:n]> c_pointer
numpy_arr = np.asarray(view)
The code above will transfer C pointer to a numpy array. However this would not free memory automaticlly, you have to free the memory by yourself or it would lead to memory leak!
A further option (in addition to the two options from the top answer: PyArray_SimpleNewFromData and just returning the typed memoryview without handling the memory) is to use the cython.view.array class.
This is a fairly low-level class that can be used to wrap existing memory. It has an attribute callback_free_data where you can set a function to be called on destruction so that it does free the memory (example code here is copied from the documentation):
cdef view.array my_array = view.array(..., mode="fortran", allocate_buffer=False)
my_array.data = <char *> my_data_pointer
# define a function that can deallocate the data (if needed)
my_array.callback_free_data = free
It exposes the buffer protocol so that you can index it, use it with typed memoryviews, or wrap it with a Numpy array (without copying) with np.asarray. The latter feature may be easier to use than PyArray_SimpleNewFromData.