C - Passing dynamic allocated 3D Matrix to function - c

In my main function i create a dynamic 3D array and succesfull alocate it.
int ***board = (int ***)malloc(counter * sizeof(int **));
for(int i = 0; i < counter; i++){
board[i] = (int **) malloc(dimension[i] * dimension[i] * sizeof(int));
}
Then i wan to pass it to a function defined as:
void readPuzzle(int board[][MAX][MAX], int *dimension, int counter,const char *);
I pass it like this:
readPuzzle(board, dimension, counter, argv[1]);
But i keep getting this error, i searched for it but never could fix it!
main.c: In function ‘main’:
main.c:22:13: warning: passing argument 1 of ‘readPuzzle’ from incompatible pointer type [-Wincompatible-pointer-types]
readPuzzle(board, dimension, counter, argv[1]);
^~~~~
In file included from main.c:4:0:
headers.h:7:6: note: expected ‘int (*)[100][100]’ but argument is of type ‘int ***’
void readPuzzle(int board[][MAX][MAX], int *dimension, int counter, const char *);

If your 2D arrays have variable dimensions, you need int ***, but this prototype
void readPuzzle(int board[][MAX][MAX], int *dimension, int counter, const char *);
isn't compatible with board passed as int *** because it required an array of 2D arrays, not a triple pointer.
So fix it like that:
void readPuzzle(int ***board, int *dimension, int counter, const char *);
but you still need to keep track of the dimensions for each "slice".
The alternative, if the 2D arrays have fixed dimensions MAX*MAX is to allocate an array of 2D arrays like this:
int (*board)[MAX][MAX] = malloc(counter*sizeof(*board));
now you can pass board as int board[][MAX][MAX]. Of course, if not all data is used, you still need to keep track of max dimensions somewhere.

Related

Incompatible pointer type for array

New learner here; I am performing a traverse on any given array but I find I get this error:
exe_3.c:18:27: warning: incompatible pointer types passing 'int *' to parameter of type 'int **' [-Wincompatible-pointer-types]
int result = traverse(&arr[6], &n);
^~~~~~~
exe_3.c:4:25: note: passing argument to parameter 'A' here
const int traverse(int *A[], int *N){
What I have tried:
#include <stdio.h>
#include <stdlib.h>
const int traverse(int *A[], int *N){
int i = 0;
int arr[*N];
while(i < *N){
arr[i] = *A[i];
i += 1;
}
return *arr;
}
int main(){
int arr[6] = {1, 2, 3, 4, 5, 6};
int n = sizeof(arr)/sizeof(arr[0]);
int result = traverse(&arr, &n);
printf("%i\n", result);
return EXIT_SUCCESS;
}
Your call traverse(&arr, &n); passes a pointer to the array arr to the function traverse.
You get the error message, because the correct type definition for a pointer to an array of integers is int(A*)[]. You have that type in the definition of the traverse function incorrect (your line 4).
You will see that this is not enough to compile your code. When accessing the elements of such an array via that pointer you need the expression (*A)[i]. You have that access in the implementation of the traverse function incorrect (your line 8).
See also here for more details: C pointer to array/array of pointers disambiguation
What I find also strange with your traverse function is that the array arr is not used completely. Only the first value is returned. I suppose your code is just not complete.

Is it possible to use format specifiers as arguments for a function

I'm trying to write a function that allows me to initialise every element of a matrix with a given value. I'd like for this function to be as generic as possible, meaning that it would be able to treat matrices of any data type (float, char, etc).
The function would obviously need as one of the argument the value that the user wants the elements of the matrix to be initialised with. Since this value could be of any kind of data type, I don't know how to go about this.
Standard functions such as printf and scanf are able to accept arguments of any kind thanks to their use of format specifiers (%d, %f, etc). This got me wondering: how and is it even possible to use format specifiers in a programmer-defined function?
Ideally, my function would look something like this:
void initMatrix(void*** matrixToInit, int nRows, int nCols, const char format, void(?) value)
So that upon calling it I would have to write something like:
char matrixOfAs[3][3];
initMatrix(&matrixOfAs, 3, 3, "%c", 'A');
Is something like this feasible? Are there other solutions to this problem?
Assuming the matrix is a proper 2-D array of the element type (an array of array of element type), and not a 1-D array of pointer to element type, you could pass a void * pointer to the first element of the matrix to be initialized, the dimensions of the matrix, the element size, and a pointer to an initial element value as illustrated by the following:
#include <string.h>
#include <stdio.h>
void initMatrix(void *matrixToInit, unsigned int nRows, unsigned int nCols,
size_t elemSize, const void *elemVal)
{
size_t offset, end;
end = nRows * nCols * elemSize;
for (offset = 0; offset < end; offset += elemSize) {
memcpy((char *)matrixToInit + offset, elemVal, elemSize);
}
}
int main(void)
{
char matrixOfAs[3][3];
int i, j;
initMatrix(&matrixOfAs[0][0], 3, 3, sizeof(char), (char []){ 'A' });
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
printf(" %c", matrixOfAs[i][j]);
}
printf("\n");
}
return 0;
}
If you do not like the compound literal array value (char []){ 'A' } which I passed to the parameter elemVal (allowing the array value to decay to a pointer to its first element), you can replace it with a pointer to an initialized variable of type char in this case, e.g. define char a = 'A'; and replace (char []){ 'A' } with &a.
To make this function generic for any data type you choose to use, just create the function that doesnt handle a spesific data type but uses function pointers instead.
It means instead of passing this function the symbol of which type the user choose and then create a case for int, case for char and case for float, pass functions that hanle each type as an argument.
For example, make the function initMatrix like:
void initMatrix(void*** matrix, int nRows, int nCols, void(*creatematrix)(void ***, int, int));
Now, Create another function that handle the creation of int **matrix, lets call it void CreateIntMatrix(void ***matrix, int m, int m); and pass a pointer to this function as an argument of initmatrix function.
Now, when you call initMatrix to handle int data types, just call it like that:
void initMatrix(&matrixOfAs, 3, 3, CreateIntMatrix);
you should create as well function that handle char, double etc..
Now, when you creating the initMatrix function, create it like that:
void initMatrix(void*** matrix, int nRows, int nCols, void(*creatematrix)(void ***, int, int)){
/*Make something*/
creatematrix(matrix, nRows, nCols)//initialize any type of matrix
/*Make something*/
}

C feeding array to function [duplicate]

Having looked around I've built a function that accepts a matrix and performs whatever it is I need on it, as follows:
float energycalc(float J, int **m, int row, int col){
...
}
Within the main the size of the array is defined and filled, however I cannot passs this to the function itself:
int matrix[row][col];
...
E=energycalc(J, matrix, row, col);
This results in a warning during compilation
"project.c:149: warning: passing argument 2 of ‘energycalc’ from
incompatible pointer type project.c:53: note: expected ‘int **’ but
argument is of type ‘int (*)[(long unsigned int)(col +
-0x00000000000000001)]’
and leads to a segmentation fault.
Any help is greatly appreciated, thank you.
The function should be declared like
float energycalc( float J, int row, int col, int ( *m )[col] );
if your compiler supports variable length arrays.
Otherwise if in declaration
int matrix[row][col];
col is some constant then the function can be declared the following way
float energycalc(float J, int m[][col], int row );
provided that constant col is defined before the function.
Your function declaration
float energycalc(float J, int **m, int row, int col);
is suitable when you have an array declared like
int * matrix[row];
and each element of the array is dynamically allocated like for example
for ( int i = 0; i < row; i++ ) matrix[i] = malloc( col * sizeof( int ) );
If the array is declared as
int matrix[row][col];
then change the function declaration to
float energycalc(float J, int m[][col], int row, int col){
The name of a two dimensional array of type T does not decay to T**.
If col is a local variable, then you need to call the function with the col parameter before matrix. This is done so that col is visible in the function.
Passing two dimensional array to a function in C is often confusing for newbies.
The reason is that they assume arrays are pointers and having lack of understanding how arrays decays to pointer.
Always remember that when passed as an argument arrays converted to the pointer to its first element.
In function call
E = energycalc(J, matrix, row, col);
matrix is converted to pointer to its first element which is matrix[0]. It means that passing matrix is equivalent to passing &matrix[0]. Note that the type of &matrix[0] is int(*)[col] (pointer to an array of col int) and hence is of matrix. This suggest that the second parameter of function energycalc must be of type int(*)[col]. Change the function declaration to
float energycalc(int col, int (*m)[col], int row, float J);
and call your function as
E = energycalc(col, matrix, row, J);
I think you can do something like this in C
float function_name(int mat_width, int mat_height, float matrix[mat_width][mat_height]) {
... function body...
}
A pointer-to-pointer is not an array, nor does it point to a two-dimensional array. It has nothing to do with arrays, period, so just forget you ever heard about pointer-to-pointers and arrays together.
(The confusion likely comes from the hordes of confused would-be programming teachers/authors telling everyone that they should use pointer-to-pointer when allocating dynamic 2D arrays. Which is just plain bad advice, since it will not allocate a real array allocated in adjacent memory cells, but rather a fragmented look-up table exploded in pieces all over the heap. See this for reference about how to actually allocate such arrays.)
Assuming that your compiler isn't completely ancient, simply use a variable length array (VLA), which is a feature introduced in the C language with the C99 standard.
#include <stdio.h>
void print_matrix (size_t row, size_t col, int matrix[row][col]);
int main (void)
{
int matrix[2][3] =
{
{1,2,3},
{4,5,6}
};
print_matrix(2, 3, matrix);
return 0;
}
void print_matrix (size_t row, size_t col, int matrix[row][col])
{
for(size_t r=0; r<row; r++)
{
for(size_t c=0; c<col; c++)
{
printf("%d ", matrix[r][c]);
}
printf("\n");
}
}

Passing Multidimensional Arrays to a function in C

I'm trying to modify a multidimensional array. This is my function code -
void rot90(int n,char **a)
{
int i,j;
int b[n][n];
for(i=n-1;i>=0;i--)
{
for(j=0;j<n;j++)
{
a[n-1-i][j]=b[j][i];
}
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
a[i][j]=b[i][j];
}
}
}
And in my main function , I am calling it as -
A is a 2d Array nxn.
rot90(n,A);
which shows the following error on compilation -
warning: passing argument 2 of ‘rot90’ from incompatible pointer type [enabled by default]
note: expected ‘char **’ but argument is of type ‘char (*)[10]’
what is the right way to do it?
Thanks.
If A is an NxN array, and you're using a VLA (which it looks like from your snippet), then the prototype needs to be either
void rot90( int n, char (*a)[n] )
or
void rot90( int n, char a[][n] )
or
void rot90( int n, char a[n][n] )
The second two forms are interpreted the same as the first; a is a pointer to an n-element array of char.

Passing a matrix of structs to a function in C

I know there are similar questions, but I still can't figure this out, even though I've been reading for 2 hours.
struct box
{
char letter;
int occupied; //0 false, 1 true.
};
void fill(struct box**, int, int, char*); //ERROR HERE**
int main(int argc, char** argv)
{
int length=atoi(argv[4]),
width=atoi(argv[5]),
char alphabet[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
struct box soup[length][width];
fill(soup, length, width, alphabet); //HERE**
}
void fill(struct box soup[][], int length, int width, char*alphabet) //AND HERE**
{
//omitted
}
These are the errors I'm getting when I compile:
warning: passing argument 1 of ‘fill’ from incompatible pointer type [enabled by default]
fill(soup, length, width, alphabet);
^
note: expected ‘struct box **’ but argument is of type ‘struct box (*)[(sizetype)(width)]’
void fill(struct box **, int, int, char*);
^
error: array type has incomplete element type
void fill(struct box soup[][], int length, int width, char*alphabet)
^
I don't get why that fails, while some other functions I have like this one, does work:
void wordsToMemory(char**, char*); //prototype
char* dictionary[Nwords];
wordsToMemory(dictionary, argv[1]); //calling the method
void wordsToMemory(char* dictionary[], char* argv) //function body
{
//omitted
}
This will get it to compile:
void fill(struct box** soup, int length, int width, char* alphabet)
or
void fill(struct box* soup[], int length, int width, char* alphabet)
When using [][] you get an error because there is no conversion from struct box* to struct box.
Array decays into pointers. When you are passing a single dimension array to a function, the function which receives the array can look like this
void fun(char a[10]) void fun(char a[]) void fun(char *a)
{ { {
... OR ... OR ...
} } }
Arrays decays into pointer, not always true...Arrays decay into pointers is not applied recursively...Means, 2D Array decays to pointer to array not to pointer to pointer so that is why you are getting the error.
When you are passing 2D array to function, the function which receives the 2D array should look like this...
void fun(char *a[10])
{
...
}
void fill(struct box**, int, int, char*);
This declaration is wrong because it says that the function's first argument has to be of type pointer to pointer to struct box, while you have no objects of type pointer to struct box in main to refer to, rather you have, as you say, a matrix (a two-dimensional array, an array of arrays) of structs.
So, the prototype
void fill(struct box [][], int, int, char *);
is almost correct, except, only the major (the first) dimension of a matrix declaration can be omitted, so we need to specify at least the width therein, which conveniently is also passed to the function, only the parameters' order has to be changed so that width is defined early enough:
void fill(int length, int width, struct box soup[][width], char *alphabet);
The function call in main is consequently:
fill(length, width, soup, alphabet);

Resources