Is this the correct method to define an 5*3 matrix using double pointers?`
int **M1;
M1 = (int **)malloc(5 * sizeof(int *));
for (i=0;i<5;i++)
{
M1[i] = (int *)malloc(3 * sizeof(int));
}`
If so, how can I assign M1[3][15] = 9 in the code and still get no error? And why am I getting a segmentation error in assigning M1[6][3]=2?
I understood after few such initializations that I created a 5*xx array, i.e. I couldn't go above 5th row but I could assign any value to the number of columns. How should I create just a 5*3 array?
In your code, you're allocating memory for 5 pointers
M1 = (int **)malloc(5 * sizeof(int *));
and later, you're trying to access beyond that, based on an unrelated value of m
for (i=0;i<m;i++)
when m goes beyond 4, you're essentially accessing out of bound memory.
A better way to allocate will be
int m = 5;
M1 = malloc(m * sizeof(*M1));
if (M1)
{
for (i=0;i<5;i++)
{
M1[i] = malloc(3 * sizeof(*M1[i]));
}
}
couldn't go above 5th row but I could assign any value to the number of columns.
NO, you can not. In any way possible, accessing out of bound memory invokes undefined behaviour.
Since Sourav tackled the UB case, I'll answer
How should I create just a 5*3 array?
Why not rely on automatic variables? Unless you've a compelling reason not to, use them
int matrix[5][3];
If you don't know the dimensions in advance, and don't prefer doing the double pointer manipulation, flatten it like this:
int *m = malloc(sizeof(int) * rows * cols);
// accessing anything from 0 to (rows * cols) - 1 is permitted
// helper to make usage easier
int get_element(int *m, int i, int j, int cols) {
return m[i * cols + j];
}
OTOH, if you only don't know the first dimension at compile-time, then you may do:
typedef int (Int5) [5]; // cols known at complie-time
int rows = 3;
Int5 *r = malloc(rows * sizeof(Int5));
r[0][0] = 1; // OK
r[0][5] = 2; // warning: out of bounds access
With this method you get a bit more type safety due to the compiler knowing the size in advice.
Related
I'm using this function to read the input matrix:
void leMatInt(int **M,int linhas,int colunas){
int i, j;
for (i = 0; i < linhas; i++){
for (j = 0; j < colunas; j++){
scanf("%d", &M[i][j]);
//printf("Leu [%d, %d]\n", i, j);
}
}
}
And I'm creating the matrix like this:
scanf("%d", &v1);
int **matriz1=(int **)malloc(v1 * sizeof(int));
for(i = 0;i < v1; i++){
matriz1[i] = (int *)malloc(v1 * sizeof(int));
}
leMatInt(matriz1, v1, v1);
The code works nicely for v1 <= 4, but if I try to input a 5v5 matrix, the code gets runtime error at the function.
matriz1 is a double pointer so while allocating memory you should write sizeof(int*). because ** pointer will holds/contains * single pointers.
int **matriz1 = malloc(v1 * sizeof(int*));
for(i = 0;i < v1; i++){
matriz1[i] = malloc(v1 * sizeof(int));
}
typecasting malloc() is discouraged.
int **matriz1=malloc(v1 * sizeof(int*));
A double (**) pointer variable will hold pointer to an int.
matriz1 is a pointer to a pointer variable (pointer to a int*).
So it will contain int* variables.
Also casting the return type of malloc is unnecessary and check the return value of malloc.
It's undefined behavior here. That's why it works for 4 unexpectedly but doesn't work for 5x5 matrices.
An example: (Considering a particular case)-
Though sizeof int is implementation defined, but it's usually 4
bytes. But sizeof pointer is usually 8 byte in 64-bit compiler.
Now to hold 5 int* variable you need 40 byte. But you are allocating 20
bytes. So you are allocating less memory than what you need. And
accessing memory that you are not permitted to, invoking undefined
behavior.
int **matriz1=(int **)malloc(v1 * sizeof(int));
This line is wrong. As already stated by other answers, the elements pointed to by matriz1 are not integers but pointers to integers, so using sizeof with a type name should be sizeof(int *) here.
Also, casting the return value of malloc() is unnecessary and arguably bad style in C.
To avoid errors like that, sizeof can also take an expression as an operand and uses the type this expression would evaluate to, which comes very handy with malloc() -- it should look like this:
int **matriz1 = malloc(v1 * sizeof *matriz1);
If you change the type of matriz1 later, sizeof *matriz1 still gives the correct element size -- it's the size of whatever matriz1 points to.
The basic question is:
For code that expects a pointer to pointer that will be syntactically indexed like a 2-dimensional array, is there a valid way to create such an array using a single allocation?†
While on the surface, it seems I am asking for how to do so (like in this question), I already understand how it could be done (see below). The problem is that there might be an alignment issue.‡
The rest of the text describes some alternatives, and then explains the method under question.
† Olaf points out a pointer to pointer is not a 2-dimensional array. The premise of the question is that 3rd party code expects a pointer to pointer passed in, and the 3rd party code will index it as a 2-dimensional array.
‡ ErikNyquist presented a possible duplicate which explains how one might perform such an allocation, but I am questioning the validity of the technique with regards to alignment of the data.
If I need to dynamically allocate a multi-dimensional array, I typically use a single allocation call to avoid an iteration when I want to free the array later.
If VLA is available, I might code it like this:
int n, m;
n = initialize_n();
m = initialize_m();
double (*array)[m] = malloc(n * sizeof(*array));
array[i][j] = x;
Without VLA, I either rely on a macro on a structure for array accesses, or I add space for the pointer table for code that expects the ** style of two-dimensional array. The macro approach would look like:
struct array_2d {
int n, m;
double data[];
};
// a2d is a struct array_2d *
#define GET_2D(a2d, i, j) (a2d)->data[(i) * x->n + (j)]
struct array_2d *array = malloc(sizeof(*array) + n * m * sizeof(double));
array->n = n;
array->m = m;
GET_2D(array, i, j) = x;
The pointer table method is more complicated, because it requires a loop to initialize the table.
struct array_p2d {
int n, m;
double *data[];
};
#define GET_P2D(a2d, i, j) (a2d)->data[i][j]
struct array_p2d *array = malloc(sizeof(*array) + n * sizeof(double *)
+ n * m * sizeof(double));
for (k = 0; k < n; ++k) {
array->data[k] = (double *)&array->data[n] + k * m;
}
GET_P2D(array, i, j) = x;
// array->data can also be passed to a function wanting a double **
The problem with the pointer table method is that there might be an alignment issue. As long as whatever type the array is of does not have stricter alignment requirements than a pointer, the code should work.
Is the above expected to always work? If not, is there a valid way to achieve a single allocation for a pointer to pointer style 2-dimensional array?
Well, your malloc allocation is guaranteed to be aligned (unless you're using a non-standard alignment), so all you need to do is to round up the pointer table size to the alignment of the data segment:
const size_t pointer_table_size = n * sizeof(double *);
const size_t data_segment_offset = pointer_table_size +
((_Alignof(double) - (pointer_table_size / _Alignof(double))) % _Alignof(double));
double **array = malloc(data_segment_offset + (n * m * sizeof(double));
double *data = (double **)(((char **) array) + data_segment_offset);
for (int i = 0; i != n; ++i)
array[i] = data + (m * i);
I want to use two-dimension array inside of some struct:
typedef struct{
int rows;
int cols;
another_struct *array[][];
}some_struct;
But seems i can't do multidimensional array of incomplete type, so i choose to go with another_struct *array[0][0];
And allocate it this way:
some_struct *allocate_some_struct(int rows, int cols){
some_struct *p;
uint32_t length;
length = sizeof(some_struct) + rows * sizeof(another_struct *[cols]);
p = malloc(length);
p->rows = rows;
p->cols = cols;
return (p);
}
But whenever i try to access it this way : ((another_struct *[p->rows][p->cols])p->array)[i],i get this error: used type 'another_struct *[p->rows][p->cols]' where arithmetic or pointer type is required.
Although (*((another_struct *(*)[p->rows][p-cols])&(p->array)))[i], work perfectly fine.
So my questions is why can't i use first syntax? Is there fundamental difference with the second one ?
In C typing is static, so it means that every type must be completely known when you operate with it (when compiling has finished). For a bidimensional array, this means that all the dimensions must be know for the language to be able to do the access to the individual cells. Access to an array is made using a formula that need the size of the already used indexed parts of it. For a cell is the cell size, but for an array of cells you must know how many cells you have in that direction.
But, there's a workaround that allows you to use indexing with the [] brackets, and doesn't need to know any size but the size of an individual cell. You have to use pointers, as in this example:
double **new_matrix(int rows, int cols)
{
double **res = malloc(rows * sizeof(double *));
int i;
for (i = 0; i < rows; i++)
res[i] = malloc(cols * sizeof(double));
return res;
}
void free_matrix(double **matrix, int rows)
{
int i;
for (i = 0; i < rows; i++) free(matrix[i]);
free(matrix);
}
...
double **matrix = new_matrix(24, 3);
matrix[12][1] /* will access correctly row 13 and column 2 element */
...
free(matrix, 24); /* will free all allocated memory */
There are solutions that allow you to allocate the whole matrix (and the pointers in one bunch (and allow to use free(3) directly on the matrix thing) but I leave this as an exercise to the reader :)
I am trying to pass in 2 2D arrays, 1 1D array and 2 integers to cudaMlloc() so that I can use it in my kernel. The 2D arrays are doubles and other is int.While the 1d array contains floats. I keep getting the error "no instance of overloaded function CudaMalloc matches the argument list.argument types are : (int,int).I dont know what I am doing wrong.
The kernel and the way i used it is below:
__global__ void getMatrix(double** cmatrix,int** data,float* angle,int x,int y){
int j = blockIdx.x * blockDim.x + threadIdx.x;
int i = blockIdx.y * blockDim.y + threadIdx.y;
int xrad,yrad;
xrad = 0;
yrad = 0;
xrad = (int)round(cos(angle[i]) * (j+1) + x);
yrad = (int)round(sin(angle[i]) * (j+1) + y);
cmatrix[i][j] = (double)data[yrad-1][xrad-1];
}
And the implementation is:
int dataFileSize = 801 * 1201 * sizeof(int);
int cmatrixSize = ANGLESIZE * RADIUS/RADSTEP * sizeof(double);
int xVarSize = sizeof(int);
int yVarSize = sizeof(int);
int** d_data;
cudaMalloc(&d_data,dataFileSize);
double** d_cmatrix;
cudaMalloc(&d_cmatrix,cmatrixSize);
float * d_angle;
cudaMalloc(&d_angle,sizeof(float) * ANGLESIZE);
int *d_x;
cudaMalloc((void**)&d_x,xVarSize);
int *d_y;
cudaMalloc((void**)d_y,yVarSize);
cudaMemcpy(d_data,data,dataFileSize,cudaMemcpyHostToDevice);
cudaMemcpy(d_cmatrix,cmatrix,cmatrixSize,cudaMemcpyHostToDevice);
cudaMemcpy(d_angle,angle,sizeof(float) * ANGLESIZE,cudaMemcpyHostToDevice);
cudaMemcpy(d_x,&x,xVarSize,cudaMemcpyHostToDevice);
cudaMemcpy(d_y,&y,yVarSize,cudaMemcpyHostToDevice);
const dim3 blockSize(ANGLESIZE,1,1);
const dim3 threadSize(1,RADIUS/RADSTEP,1);
getMatrix<<<blockSize,threadSize>>>(d_cmatrix,d_data,d_angle,d_x,d_y);
cudaMemcpy(cmatrix,d_cmatrix,cmatrixSize,cudaMemcpyDeviceToHost);
cudaFree(d_data);
cudaFree(d_cmatrix);
cudaFree(d_angle);
cudaFree(d_x);
cudaFree(d_y);
You're mentioning an error with cudaMalloc
This line is not correct:
int *d_y;
cudaMalloc((void**)d_y,yVarSize);
it should be:
int *d_y;
cudaMalloc((void**)&d_y,yVarSize);
^
add this ampersand
although you've hidden that error from the compiler by your (void **) cast, so that is not what the compiler is flagging.
You cannot allocate 2D arrays like this with cudaMalloc:
int** d_data;
cudaMalloc(&d_data,dataFileSize);
double** d_cmatrix;
cudaMalloc(&d_cmatrix,cmatrixSize);
And these will throw compiler errors, because cudaMalloc expects a ** argument, not ***.
It's recommended that you flatten those arrays and pass them as 1D arrays, and if needed do subscript arithmetic in your kernel to simulate 2D. If you really want to learn how to pass a 2D array, search on CUDA 2D array to get some ideas.
Whether there are other errors in your code is difficult to say since you have not provided a complete code.
Is it possible to write a function which accept 2-d array when the width is not known at compile time?
A detailed description will be greatly appreciated.
You can't pass a raw two-dimensional array because the routine won't know how to index a particular element. The 2D array is really one contiguous memory segment.
When you write x[a][b] (when x is a 2d array), the compiler knows to look at the address (x + a * width + b). It can't know how to address the particular element if you don't tell it the width.
As an example, check http://www.dfstermole.net/OAC/harray2.html#offset (which has a table showing how to find the linear index for each element in an int[5][4])
There are two ways to work around the limitation:
1) Make your program work with pointer-to-pointers (char *). This is not the same as char[][]. A char * is really one memory segment, with each value being a memory address to another memory segment.
2) Pass a 1d pointer, and do the referencing yourself. Your function would then have to take a "width" parameter, and you could use the aforementioned formula to reference a particular point
To give a code example:
#include <stdio.h>
int get2(int *x) { return x[2]; }
int main() {
int y[2][2] = {{11,12},{21,22}};
printf("%d\n", get2((int *)y));
}
This should print out 21, since y is laid out as { 11, 12, 21, 22 } in memory.
C supports variable-length arrays. You must specify the width from a value known at run-time, which may be an earlier parameter in the function declaration:
void foo(size_t width, int array[][width]);
One way is use the good old "pointer to array of pointers to arrays" trick coupled with a single continuous allocation:
/* Another allocation function
--------------------------- */
double ** AnotherAlloc2DTable(
size_t size1, /*[in] Nb of lines */
size_t size2 /*[in] Nb of values per line */
)
{
double ** ppValues;
size_t const size1x2 = size1*size2;
if(size1x2 / size2 != size1)
return NULL; /*size overflow*/
ppValues = malloc(sizeof(*ppValues)*size1);
if(ppValues != NULL)
{
double * pValues = malloc(sizeof(*pValues)*size1x2);
if(pValues != NULL)
{
size_t i;
/* Assign all pointers */
for(i=0 ; i<size1 ; ++i)
ppValues[i] = pValues + (i*size2);
}
else
{
/* Second allocation failed, free the first one */
free(ppValues), ppValues=NULL;
}
}/*if*/
return ppValues;
}
/* Another destruction function
---------------------------- */
void AnotherFree2DTable(double **ppValues)
{
if(ppValues != NULL)
{
free(ppValues[0]);
free(ppValues);
}
}
Then all you have to do is pass a char ** to your function. The matrix is continuous, and usable as mat[x][y].
Possible accessor functions:
int get_multi(int rows, int cols, int matrix[][cols], int i, int j)
{
return matrix[i][j];
}
int get_flat(int rows, int cols, int matrix[], int i, int j)
{
return matrix[i * cols + j];
}
int get_ptr(int rows, int cols, int *matrix[], int i, int j)
{
return matrix[i][j];
}
An actual multi-dimensional array and a fake one:
int m_multi[5][7];
int m_flat[5 * 7];
Well-defined ways to use the accessor functions:
get_multi(5, 7, m_multi, 4, 2);
get_flat(5, 7, m_flat, 4, 2);
{
int *m_ptr[5];
for(int i = 0; i < 5; ++i)
m_ptr[i] = m_multi[i];
get_ptr(5, 7, m_ptr, 4, 2);
}
{
int *m_ptr[5];
for(int i = 0; i < 5; ++i)
m_ptr[i] = &m_flat[i * 7];
get_ptr(5, 7, m_ptr, 4, 2);
}
Technically undefined usage that works in practice:
get(5, 7, (int *)m_multi, 4, 2);
[Warning - this answer addresses the case where the number of columns - the WIDTH - is known]
When working with 2D arrays, the compiler needs to know the number of columns in your array in order to compute indexing. For instance, if you want a pointer p that points to a range of memory to be treated as a two-dimensional set of values, the compiler cannot do the necessary indexing arithmetic unless it knows how much space is occupied by each row of the array.
Things become clearer with a concrete example, such as the one below. Here, the pointer p is passed in as a pointer to a one-dimensional range of memory. You - the programmer - know that it makes sense to treat this as a 2D array and you also know (must know) how many columns are there in this array. Armed with this knowledge, you can write code to create q, that is treated by the compiler as a 2D array with an unknown number of rows, where each row has exactly NB columns.
I usually employ this when I want the compiler to do all the indexing arithmetic (why do it by hand when the compiler can do it?). In the past, I've found this construct to be useful to carry out 2D transposes from one shape to another - note though that generalized 2D transposes that transpose an MxN array into an NxM array are rather beastly.
void
WorkAs2D (double *p)
{
double (*q)[NB] = (double (*)[NB]) p;
for (uint32_t i = 0; i < NB; i++)
{
for (uint32_t j = 0; j < ZZZ; j++) /* For as many rows as you have in your 2D array */
q[j][i] = ...
}
}
I believe a nice solution would be the use of structures.
So I have an example for 1d-Arrays:
Definition of the struct:
struct ArrayNumber {
unsigned char *array;
int size;
};
Definition of a function:
struct ArrayNumber calcMultiply(struct ArrayNumber nra, struct ArrayNumber nrb);
Init the struct:
struct ArrayNumber rs;
rs.array = malloc(1);
rs.array[0] = 0;
rs.size = 1;
//and adding some size:
rs.size++;
rs.array = realloc(rs.array, rs.size);
hope this could be a solution for you. Just got to change to a 2d Array.