I am writing code for the shortest path in a maze using a stack. But I keep getting this: error: conflicting types for 'Pass'
This is my code
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
#define N 6
#define length N * N
typedef struct
{
int x;
int y;
}Point;
typedef struct
{
Point* top;
Point* end;
int Capacity;
}Stack;
//Declaration
void PathPrint();
void Solution(Point beg, Stack* path);
void InitStack(Stack* s);
void Pass(Point now, int* arr);
void Push(Stack* s, Point x);
void Pop(Stack* s);
int IsEmpty(Stack* s);
Stack Path; //the path in maze
Stack* s = &Path;
Point beg;
Point end;
int count = 0;
void PathPrint()
{
int x = 0;
int y = 0;
int i = 0;
Point* temp = s->end;
while(s->top != s->end)
{
i ;
x = s->end->x;
y = s->end->y;
s->end ;
printf("(%d,%d) ",x,y);
}
s->end = temp;
}
//Function to check whether the path is passable
void Pass(Point now, int arr[N][N])
{
if(end.x == now.x && end.y == now.y)
{
count ;
printf("%d: \n", count);
PathPrint();
Point p = Pop(s);
arr[p.x][p.y] = 1;
return;
}
//checking the direction
if(1 == arr[now.x-1][now.y] && now.x - 1 >= 0)
{
Point up;
up.x = now.x-1;
up.y = now.y;
Push(s, up);
arr[now.x - 1][now.y] = -1;
Pass(up, arr);
}
if(1 == arr[now.x 1][now.y] && now.x 1 < N)
{
Point down;
down.x = now.x 1;
down.y = now.y;
Push(s, down);
arr[now.x 1][now.y] = -1;
Pass(down, arr);
}
if(1 == arr[now.x][now.y-1] && now.y - 1 >= 0)
{
Point left;
left.x = now.x;
left.y = now.y - 1;
Push(s, left);
arr[now.x][now.y-1] = -1;
Pass(left, arr);
}
if(1 == arr[now.x][now.y 1] && now.y 1 <N)
{
Point right;
right.x = now.x;
right.y = now.y 1;
Push(s, right);
arr[now.x][now.y 1] = -1;
Pass(right, arr);
}
Point p = Pop(s);
arr[p.x][p.y] = 1;
}
What does this error mean, and how could I correct it? In addition, the Pass function is to checks the direction and the path that is accessible. On a different note, this is not a complete code, but I think the main problem is in this part of the code.
CodePudding user response:
The prototype for Pass
doesn't match the definition.
You've declared Pass
as:
void Pass(Point now, int* arr);
But defined it as:
void Pass(Point now, int arr[N][N])
{
...
The type of the second parameter doesn't match. So change the declaration to match the definition:
void Pass(Point now, int arr[N][N]);
CodePudding user response:
Arrays and pointers, especially when used as function parameters, are a bit tricky. Arrays decay to pointers more often than the wave function collapses in quantum mechanics, but the two things are still not the same.
An easy way to see it is to ask for the size of objects. A pointer has the size of a pointer, regardless of the size of what it points to, while an array has the size of all the objects in the array. So with
// pointer of NxN integers
int *ip = malloc(N * N * sizeof *ip);
// array of NxN integers
int ia[N][N];
printf("sizeof(ip) == %zu, sizeof(ia) == %zu\n",
sizeof(ip), sizeof(ia));
you might see that pointers are eight bytes, say, but the array is 6x6x4 bytes if integers are four bytes (and a char is one byte).
In practise, an array is usually just a pointer to where the data sits, but it is a different type nevertheless.
This isn't that complicated, but this is C, so of course there is more to it.
If we write functions such as these
void f(int *ip)
{
printf("f: sizeof(ip) == %zu\n", sizeof(ip));
}
void g(int *ia); // notice prototype
void g(int ia[N])
{
// you probably get a warning here...
printf("g: sizeof(ia) == %zu\n", sizeof(ia));
}
you might reasonably assume that the integer pointer in f
and the integer array in g
are also different. But they are not. And as the prototype above the definition of g
hints at, it is because the array in g
isn't an array at all, it is a pointer. The array as a function parameter decays to a pointer; the full data block in an array isn't copied as a value to the function, you only get a pointer to where the data sits. So an array as a function argument silently decays to a pointer (and your compiler will likely warn you that when you ask for the size of it, you get the size of a pointer and not the size of the array).
You can call either f
or g
with pointers or arrays, and C will not complain. There isn't any real difference between pointers and arrays here; the arrays are automatically translated into pointers in g
.
An array argument and a pointer argument is the same, as far as C is concerned.
Why doesn't your code work, then? If an array becomes a pointer, it should. But not so fast. The array does become a pointer, but it doesn't become a pointer to the underlying type. You have a two-dimensional array (or, really, an array of arrays). That decays to a pointer to the kind of elements inside the array, but those elements are (one-dimensional) arrays, not integers.
We can try writing a function with a two-dimensional array and see what happens:
void g(int (*ia)[N]); // notice prototype
void g(int ia[N][N])
{
// you probably get a warning here...
printf("g: sizeof(ia) == %zu\n", sizeof(ia));
printf("g: sizeof(*ia) == %zu\n", sizeof(*ia));
}
As the prototype hints, the ia[N][N]
array argument is really a pointer, but it is a pointer to integer arrays of length N
(type int (*)[N]
). The compiler should warn you that ia
decays to a pointer, so sizeof(ia)
is the size of a pointer. What ia
points to, however, is still arrays of length N
, and the size of *ia
reflects that.
There is some sense to this. When we do pointer arithmetic on array-like memory, the step size should be the size of the underlying elements. With an integer pointer, ip
, you expect ip[2] == *(ip 2)
to be the third element from ip
. If the elements are integers, you want the third integer, not the third bit or byte or something third. That means that ip i
should be address ip i*(sizeof *ip)
. If your elements are arrays, they should still be ip i*(sizeof *ip)
so sizeof *ip
has to be the size of the underlying arrays. If that size was the size of integers, we couldn't do pointer arithmetic or indexing with multi-dimensional arrays.
If you want multi-dimensional arrays as function arguments, you either have to make the type the actual array or a pointer to everything-but-the-first dimension arrays (like the prototype for g
above).
There is nothing wrong with using a flat data pointer, the data is played out like that, so you could use a plain integer pointer. Then you have to adjust for that if you do pointer arithmetic. Otherwise, you just have to make sure that the prototype match the definition.
Arrays and pointers are tricky, because arrays will behave like pointers so often that it is easy to forget that they are different beasts. You ran into a case where their differences are not hidden. It generally happens with multi-dimensional arrays. I hope this explanation cleared things up a little bit. Otherwise, the fix is simple: change the prototype so it matches the type of the defintion.