This question already has answers here:
Why cannot use pointer of pointer as parameter to declare a function receive pointer of array
(2 answers)
Closed 6 years ago.
Here is code :
void nextGeneration(int **board) {
int editBoard[row][col];
...
displayBoard(editBoard);
}
void displayBoard(int **board) {
...
}
I get this error msg:
GOL.c: In function ‘nextGeneration’: GOL.c:64: warning: passing
argument 1 of ‘displayBoard’ from incompatible pointer type GOL.c:28:
note: expected ‘int **’ but argument is of type ‘int (*)[(long
unsigned int)(col)]’
I just don't know how to point 2D array that will be accepted to void displayBoard(int **board) function.
How can I do that?
Thank you very much
An array passed to a function is implicitly converted to pointer to its first element.
So if such an array like
int editBoard[row][col];
is passed to a function as an argument it is converted to type int ( * )[col]. The types int( * )[col] and int ** are two incompatible different types.
If the compiler supports variable length arrays then you can declare your function like
void nextGeneration( size_t row, size_t col, int board[row][col] );
or
void nextGeneration( size_t row, size_t col, int board[][col] );
or
void nextGeneration( size_t row, size_t col, int ( *board )[col] );
These three declarations declare the same one function.
If the compiler does not support VLAs but the value col is defined as a constant (using #define or an enumerator) then you again can use these declarations.
Another approach is to interpret the array used as an argument as a one dimensional array. In this case you can declare the function like
void nextGeneration( int *board, size_t row, size_t col );
and pass the array like
nextGeneration( ( int * )editBoard, row, col );
A double pointer is not a 2D array, but you can do it using a single pointer
#include <stdio.h>
#define COL_WIDTH 2
int displayBoard(int *board, int row, int col)
{
// editBoard[row][col]
return board[(COL_WIDTH*row)+col];
}
int main(void)
{
int board[2][COL_WIDTH] = { {1,2}, {3,4} };
printf("%d\n", displayBoard((int *)(board), 1, 1));
printf("%d\n", displayBoard((int *)(board), 0, 1));
}
Like this
void nextGeneration(int **board) {
int editBoard[row][col];
...
displayBoard(editBoard);
}
void displayBoard(int board[][col]) {
...
}
Related
I am currently building a Matrix calculator to add matrices, and for some reason when I add two matrices together, the correct answers for each point in matrix addition get spaced out, and in between them are zeros.
For example,
1 1 1
1 1 1
1 1 1
+
1 1 1
1 1 1
1 1 1
results in
2 0 2
0 2 0
2 0 2
instead of a matrix full of twos .
here is the code for the printing and adding function for the matrices
void printMatrix(int matriks,int matrix[3][3]) {
int row;
int column;
printf("matriks %d:\n",matriks);
for (row = 0; row < 3; row++) {
for (column = 0; column < 3; column++) {
printf(" %d", matrix[row][column]);
}
printf("\n");
}
}
void addMatrices(int m1[3][3], int m2[3][3], int *result[3][3]) {
int row;
int col;
for (row=0; row < 3; row++) {
for (col=0; col<3;col++) {
result[row][col] = m1[row][col] + m2[row][col];
}
}
}
and this is how theyre called in main()
int result[3][3];
int sampleM1[3][3] = {{1,1,1}, {1,1,1}, {1,1,1}};
int sampleM2[3][3] = {{1,1,1}, {1,1,1}, {1,1,1}};
addMatrices(sampleM1,sampleM2,&result);
printMatrix(0,result);
any help would be appreciated. Thanks!
Don't treat result as a pointer to a two-dimensional array, arrays are, when passed to a function, implicitly converted to a pointer to the first element of that array. So you're doing an extra level of indirection above what you need.
In other words, the function declaration should be:
void addMatrices(int m1[3][3], int m2[3][3], int result[3][3]) {
and the call should be:
addMatrices(sampleM1,sampleM2,result);
A decent compiler should have warned you of this:
prog.c: In function ‘addMatrices’:
prog.c:21:30: error: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
26 | result[row][col] = m1[row][col] + m2[row][col];
| ^
prog.c: In function ‘main’:
prog.c:30:32: error: passing argument 3 of ‘addMatrices’ from incompatible pointer type [-Werror=incompatible-pointer-types]
37 | addMatrices(sampleM1,sampleM2,&result);
| ^~~~~~~
| |
| int (*)[3][3]
prog.c:16:51: note: expected ‘int * (*)[3]’ but argument is of type ‘int (*)[3][3]’
20 | void addMatrices(int m1[3][3], int m2[3][3], int *result[3][3]) {
| ~~~~~^~~~~~~~~~~~
And just a bit of advice: once you start creating higher-level data structures, it's best to have them act much the same as C++ classes. In other words, place them into their own header and source files as specific types, rather than having to deal with the general types provided by C (like arrays).
For example, have a structure along the lines of:
// Everything you need to know about a matrix (of integers).
typedef struct {
size_t rows, cols;
int *data;
} tIntMatrix; // Poor man's template :-)
and provide functions to manipulate the specialised types directly:
// Allocate and de-allocate functions.
tIntMatrix *IntMatrixCreate(size_t rows, size_t cols);
tIntMatrix *IntMatrixCreateAndInit(size_t rows, size_t cols, int *values);
void IntMatrixDestroy(tMatrix *matrix);
// Get and set functions.
int IntMatrixGet(size_t row, size_t col);
void IntMatrixSet(size_t row, size_t col, int value);
void IntMatrixSetRow(size_t row, int *values);
void IntMatrixSetCol(size_t col, int *values);
void IntMatrixSetAll(int *values);
// Matrix manipulation functions, whatever is needed.
void IntMatrixAdd(tMatrix *m1, tMatrix *m2, tMatrix *sum);
void IntMatrixMult(tMatrix *m1, tMatrix *m2, tMatrix *product);
void IntMatrixInvert(tMatrix *m1, tMatrix *inversion);
// Traverse cells with a callback function.
// Function receives, for each cell: rows, cells, row, cell, value.
typedef void (*)(size_t, size_t, size_t, size_t, int) IntMatrixCb;
void IntMatrixProcess(tIntMatrix *matrix, IntMatrixCb callback);
C can be (at least partially) object-oriented, it just takes a little more work, but doing so provides much the same safety as those languages that are inherently object oriented, like encapsulation in this case.
By that, I mean the internal data structure is hidden<sup(a) from you, all you need to know, in order to be able to use the matrices, is the API.
Then, with use of a callback function:
void cbPrint(int size_t rows, size_t cols, size_t row, size_t col, int value) {
printf("%d", value);
putchar(col == cols - 1 ? '\n' : ' ');
}
Your main code then becomes something like:
tIntMatrix *sampleM1 = IntMatrixCreateAndInit(3, 3, {
1, 1, 1,
1, 1, 1,
1, 1, 1
});
tIntMatrix *sampleM2 = IntMatrixCreateAndInit(3, 3, {
1, 1, 1,
1, 1, 1,
1, 1, 1
});
tIntMatrix *result = IntMatrixCreate(3, 3);
IntMatrixAdd(sampleM1, sampleM2, result);
puts("Matriks 0:"); IntMatrixProcess(result, cbPrint);
<sup(a) Yes, I know you can see the rows/cols/data structure but you don't have to use it if the API is any good. And, you can hide it behind an opaque pointer if you really want it hidden.
When you're compiling, turn warnings on, e.g. on gcc via -Wall.
If you would have done that, you would have seen a bunch of warnings as can be seen here: https://godbolt.org/z/79a7drWar
You should know, that arrays will decay to pointer if passed as argument to a function (see: https://en.cppreference.com/w/c/language/array#Array_to_pointer_conversion).
Change
void addMatrices(int m1[3][3], int m2[3][3], int *result[3][3]);
to
void addMatrices(int m1[3][3], int m2[3][3], int result[3][3]);
and call it without the address of operator
addMatrices(sampleM1,sampleM2,result);
I am trying to print an array through a function by using call by reference but keep getting a warning:
passing argument 1 of 'test' from incompatible pointer type [-Wincompatible-pointer-types]
I tried replacing test(&arr, n); with test(arr, n);, test(*arr, n);, test(&arr[], n);, test(*arr[], n);, test(&arr[], n);
but nothing worked, what am I doing wrong?
#include<stdio.h>
void test(int *a[], int b);
void main()
{
int arr[]={1, 2, 3, 4, 5}, i, n=5;
test(&arr, n);
}
void test(int *d[], int n)
{
int i;
for(i=0; i<n; i++)
{
printf("%d", *d[i]);
}
}
How do you pass an array to a function
Just by using a pointer of the array element type:
void test(int *a, int b);
If you then pass an array to the function:
test(arr);
... the C compiler will pass a pointer to the first element of the array (&(arr[0])) to the function.
Note that you don't use the & in this case.
Inside the function you can use array operations:
void test(int * arr)
{
arr[3] = arr[2];
}
(In your case: printf("%d\n", arr[n]);)
(This is true for any kind of pointer data type with exception of void *. The C compiler assumes that the pointer points to the first element of an array if you use array operations with pointer data types.)
"passing argument 1 of 'test' from incompatible pointer type"
As far as I know, [] in a function argument is not interpreted as array, but as pointer. For this reason, ...
void test(int *a[], int b);
... is interpreted as:
void test(int **a, int b);
... which means that the C compiler expects a pointer to an array of pointers (int *), not to an array of integers (int).
It's much simpler than that. In the example below I'm using size_t to express array size, it's an unsigned integer type specifically meant to be used for that purpose.
#include <stdio.h>
// you can use the size parameter as array parameter size
void test (size_t size, int arr[size]);
int main (void) // correct form of main()
{
int arr[]={1, 2, 3, 4, 5};
test(5, arr);
}
void test (size_t size, int arr[size])
{
for(size_t i=0; i<size; i++) // declare the loop iterator inside the loop
{
printf("%d ", arr[i]);
}
}
I am trying understand how pointers works in C. I am trying a simple case where an array, and a pointer to array are the arguments of a function which will copy the elements of the first one in the second one.
I have written this code
#include <stdio.h>
#define TAM 32
typedef int TablaArray[32];
void copyArray(TablaArray, TablaArray*, int);
void main(){
int t1[] = {1,2,3,4};
int t2[4];
copyArray(t1, t2,4);
for(int i = 0; i <= 3; i ++){
printf("%d - %d\n", t1[i], t2[i]);
}
}
void copyArray(TablaArray t1, TablaArray *t2, int tam){
for(int i = 0; i<tam-1; i++){
printf("%d\n", t1[i]);
*t2[i] = t1[i];
}
}
I am expecting to get something like this with the printf expression:
1 - 1
2 - 2
3 - 3
4 - 4
But definitely I don't know the way... I have been looking in stackoverflow and because I am sure this trivial question is already answered... but I didn't find it...
You need to make sure you are passing two int pointers pointing to both arrays. In your code only one of the arguments is a pointer. The code below should make it more clear:
#include <stdio.h>
void copyArray(int * arr1, int * arr2, int size);
int main(void)
{
int t1[] = {1,2,3,4};
int t2[4];
copyArray(t1, t2,4);
for(int i = 0; i <= 3; i ++)
{
printf("%d - %d\n", t1[i], t2[i]);
}
return 0;
}
void copyArray(int * arr1, int * arr2, int size)
{
for(int i = 0; i < size; i++)
{
printf("%d\n", arr1[i]);
arr2[i] = arr1[i];
}
return;
}
Edit: in what you have written, a TablaArray * is a pointer to an array of 32 ints, while you need an int *
typedef int TablaArray[32];
is bad practice
The problem is connected with array to pointer decay and then with pointer arithmetics:
Pointer decay means that if you pass an array-object of type int x[32] as argument to a function, then it "decays" to a pointer like int *, which points to the first element of the integer array. So be aware that if you pass an int x[32]-object, it's actually passed by reference (the array is not copied) and you may alter the contents of the array in the function.
Now pointer arithmetics:
Incrementing a pointer (or accessing an array through array subscripting) implicitly does pointer arithmetics, and the number of bytes added to the initial value depends on the type of the object to which the pointer points:
typedef int Array10[10];
Array10 arr = { 1,2,3,4,5,6,7,8,9,0 };
int *x = arr; // arrayOfInts decays to a pointer; x points to the &arr[0]
x++; // in terms of bytes, x is incremented by sizeof(int) bytes
int i = x[3]; // gets the int-value on the address of x + 3*sizeof(int)
Array10 *arr10ptr = arr;
arr10ptr++; // in terms of bytes, x is incremented by sizeof(Array10) bytes, which is 10*sizeof(int)
arr10ptr[3]; // 3*sizeof(Array10), i.e. 3*10*sizeof(int)
Now it should be clear why a function parameter being declared as a pointer to an array of int[32] behaves different from a function parameter being declared as an int[32].
So you could correct your program as follows, now knowing that TablaArray t2 will be a reference to the underlying array anyway:
void copyArray(TablaArray t1, TablaArray t2, int tam){
for(int i = 0; i<tam; i++){
printf("%d\n", t1[i]);
t2[i] = t1[i];
}
}
Hope it helps.
Compile with warnings enabled. If you used gcc -Wall -Werror, you would get the following errors:
luis.c:10:6: error: return type of ‘main’ is not ‘int’ [-Werror=main]
void main(){
^~~~
luis.c: In function ‘main’:
luis.c:15:19: error: passing argument 2 of ‘copyArray’ from incompatible pointer type [-Werror=incompatible-pointer-types]
copyArray(t1, t2,4);
^~
luis.c:8:6: note: expected ‘int (*)[32]’ but argument is of type ‘int *’
void copyArray(TablaArray, TablaArray*, int);
^~~~~~~~~
cc1: all warnings being treated as errors
The first one is simple, it should be int main.
The second one is a bit harder to see exactly because you used a typedef. So your prototype is now
void copyArray(int *, int (*)[32], int);
With the second value being a pointer-to-array that by itself is a construct that is not used often.
Instead, you'd just need two pointers to int here, and the size of an array should perhaps use size_t instead:
void copyArray(int *, int *, size_t);
void copyArray(int *t1, int *t2, size_t n){
for (int i = 0; i < tam; i++) {
t2[i] = t1[i];
}
}
Finally, if you use a C99, C11 compiler, it could be nice to use the variable-length arrays arrays to tell that one of the parameters tell the sizes of the arrays; for that we need to reorder the parameters:
void copyArray(size_t, int[*], int[*]);
void copyArray(size_t n, int t1[n], int t2[n]) {
...
}
void copyArray(TablaArray, TablaArray, int); // prototype
void copyArray(TablaArray t1, TablaArray t2, int tam){
for(int i = 0; i<tam; i++){
printf("%d\n", t1[i]);
t2[i] = t1[i];
}
}
this will help
// much faster
#include <string.h>
void copyArray(TablaArray t1, TablaArray t2, int tam){
memcpy(t2, t1, sizeof(t1[0]) * tam);
}
In Your Copy function you were copying the same value of T1 to T2 on the Address Of T2. you can do it with out pointers but pointers helps you to refer the Address
I am currently doing the fifteen exercise in CS50's Problem set 3. However, I am stuck in figuring out the syntax to pass a multi-dimensional array as an argument to a function. For instance, the following code (which prints out some numbers in an array) compiles and works:
#include <stdio.h>
void func(int array[], int size);
int main()
{
int size = 3;
int array[3] = {1,2,3};
func(array,size);
printf("Done\n");
}
void func(int array[], int size)
{
printf("%i %i %i\n", array[0],array[1], array[2]);
}
But this doesn't:
#include <stdio.h>
void func(int array[][], int size);
int main()
{
int size = 3;
int array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
func(array,size);
printf("Done");
}
void func(int array[][], int size)
{
printf("%i %i %i\n", array[0][0],array[1][1], array[2][2]);
}
This is the error provided by clang:
test.c:3:20: error: array has incomplete element type 'int []'
void func(int array[][], int size);
^
test.c:13:20: error: array has incomplete element type 'int []'
void func(int array[][], int size)
Can anyone explain to me what's wrong with my syntax? I don't quite understand the error messages given to me by clang.
The function func() expects a pointer to int but you are passing a pointer to an array. Hence, the errrors.
It's because an array gets converted into a pointer to its first element when you pass it to a function.
You can change the function prototype and definition to receive a pointer to an array:
void func(int (*array)[3], int size);
int main()
{
int size = 3;
int array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
func(array,size);
printf("Done");
}
void func(int (*array)[3], int size) {
...
}
Note that your array is initialized with size 3x3. So the array size has to 3x3 at least.
C99 allows to you pass dimensions. So you can write it like this too:
void func(int x, int y, int a[x][y]);
int main()
{
int size = 3;
int array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
func(3, 3, array);
printf("Done");
}
void func(int x, int y, int array[x][y])
{
printf("%i %i %i\n", array[0][0],array[1][1], array[2][2]);
}
An array is not a type in C! Internally, it is always handled as a pointer, hence, a pointer to the array is passed as argument and not the array itself.
If you intend to pass arrays as arguments (and not just pointers), you should rethink your design!
If you still need to do this wrap the array into a structure and pass the structure.
struct astruct
{
int size;
int array[3];
};
A declaration like int a[][] isn't sensible, since the compiler must know the size of all dimensions (except of the outermost) to calculate the memory address on access.
I.e. if an array is declared as
int array[][a][b];
The memory address for access to
array[2][1][3];
is calculated by
base_address + (2*a*b + 1*b + 3) * sizeof int
Without knowing a and/or b, this calculation would not be possible.
Simply tell the function to expect a multi-dimensional array:
void func (int array[3][3], int size);
Or if you want the function to be completely flexible:
void func (int x, int y, int array[x][y]);
You need to specify size of array when declaring prototype as well as while defining function . Right now it is of incomplete type .
Try this instead -
void func(int array[][3], int size)
I'm working with dynamic arrays and this is the declaration:
int *vetor = (int *) malloc (tam*sizeof(int));
vetorAleatorio (vetor, tam); //chamando função abaixo
but when I try to pass it as parameter to this function:
void vetorAleatorio(int **vet, int size) {
int i;
for (i=0; i<size; i++)
vet[i] = rand() %1000;}
I have the following errors:
[Warning] assignment makes pointer from integer without a cast
[Warning] passing arg 1 of `vetorAleatorio' from incompatible pointer type
Someone know how this is happening?
Your function syntax:
void vetorAleatorio(int **vet, int size)
should be:
void vetorAleatorio(int *vet, int size)
^
// remove one *
[Warning] assignment makes pointer from integer without a cast
if you use double * as int ** for vet, then its type mismatch as follows:
vet[i] = rand() %1000
^ ^
| int // rand() %1000 returns a int
type is int*
// vet[i] == *(vet + i) == *(pointer to pointer of int) = pointer int = int*
Warning-2: passing arg 1 of `vetorAleatorio' from incompatible pointer type
Understand In your code you according to void vetorAleatorio(int **vet, int size) declaration you are calling function in wrong way: vetorAleatorio (vetor, tam);, you are passing address of int = pointer to int, and argument need address of pointer to int = pointer to pointer to int.
You just need one rectification as I suggested above.
int **vet declares that the vet argument is a pointer to a pointer to int. i.e. an array of arrays of integers. It looks like you just want to pass a pointer to a single vector so you should declare the argument as type int* instead
void vetorAleatorio(int *vet, int size) {
Your function signature for vetorAleatorio is wrong - change:
void vetorAleatorio(int **vet, int size)
to:
void vetorAleatorio(int *vet, int size)
Also note that you should never cast the result of malloc in C, so change:
int *vetor = (int *) malloc (tam*sizeof(int));
to:
int *vetor = malloc (tam*sizeof(int));
vetor is of type int *, where veteroAleatorio is expecting an int **
You should have
void vetorAleatorio(int *vet, int size) {
int i;
for (i=0; i<size; i++)
vet[i] = rand() %1000;}
You have an extra *. This should work:
void vetorAleatorio(int *vet, int size)
You are passing in a pointer to an int (the variable vetor), so your function declaration should accept a pointer to an int.