0

I'm trying to run the following code on C:

#include "ex1_1.h"

void path(char **adj_mat, int u, int v)
{
        printf("test\n");
        char temp = *adj_mat[1];
        putchar(temp);
}

int main()
{
    int u = 5;
    int v = 5;
    char mat[5][5]={
    {'0', '1', '1', '1', '0'},
    {'0', '0', '0', '0', '1'},
    {'0', '0', '0', '0', '0'},
    {'0', '0', '0', '0', '0'},
    {'0', '0', '0', '0', '0'}
    };
    char** adj_mat = (char**)&mat;
    printf("Mtest\n");
    path(adj_mat, u, v);
    return 1;
}

and I'm getting "Segmentation fault".

I don't know why, I'm guessing that it's related to how I'm using putchar() with multidimensional array pointers.

Thanks.

judith
  • 805
  • 2
  • 12
  • 17

3 Answers3

3

A char[5][5] is not a char **.

Declare your path function as one of these (they are equivalent):

void path(char (*adj_mat)[5], int u, int v)
void path(char adj_mat[5][5], int u, int v)

and use it like

path(mat, u, v);

Update: Now to the reason for the segfault.

mat is a 5-array of 5-arrays of char, which will "decay" into a pointer to 5-arrays of char when used as an expression. This means that mat can be used as if it is a pointer to a 5-array. In general a n-array of type T will decay into a pointer of type T (note that T does not decay!).

So note you use mat as an expression when you pass it to your function pass(). In C it is not possible to pass an array as-is to a function, but it can only "receive" pointers.

So what's the difference between a pointer to pointer of char and a pointer to a 5-array of char? Their type. And their sizes.

Suppose you have a pointer to a pointer to a char - let's call it p and we have a pointer to a 5-array q. In short: char **p and char (*q)[5].

When you write p[i], this will be equivalent to *(p+i). Here you have pointer arithmetic. p+i has the value (which is an adress) p plus i*sizeof(char *) because p points to a char *.

When you look at q, q+i would have the value q plus i*sizeof(char[5]).

These will almost always be different!


Update (real answer now): It's even worse in your case as you are "forcing" char (*q)[5] "to be" a char p** (via your invalid typecast), so in your call

char temp = *adj_mat[1];

adj_mat[1] will look at the 2nd row of your matrix an try to interpret its value as a pointer (but it is a 5-array!), so when you then dereference via *adj_mat[1] you will land somewhere in nirvana - segfault!

Anthales
  • 1,158
  • 6
  • 10
1

The conversion (char**)&mat is undefined behavior. &mat is char(*)[5][5] (In words, pointer to array of 5 arrays of 5 chars), and you can't convert it to pointer to pointer to char.

I would write path like (assuming C99):

void path(char *arr,int u,int v) {
 char (*adj_mat)[v]=arr;
 ...
}
asaelr
  • 5,438
  • 1
  • 16
  • 22
  • Minor comment: &mat is char[5][5], since the addressof of an array returns the array reference itself (since you can't pass an array by value, only by reference). AFAIK, &mat should be the same as mat. –  Apr 28 '12 at 18:15
  • 1
    @H2CO3 as far as I know, you are wrong. the value of `&mat` is the same as of `mat`, but the types are different. `&mat` is pointer to array, and you can dereference it like any pointer. (consider `mat[0]` against `&mat[0]` - they have the same relation) – asaelr Apr 28 '12 at 18:20
  • you're right in the question of types, but their value is the same. –  Apr 28 '12 at 18:21
0

Change the line

char temp = *adj_mat[1];

to

char temp = adj_mat[1];

The problem is that in

*adj_mat[1];

you try to dereference a pointer to an invalid address, namely the ASCII code of '1' (I suppose).

Sven Hager
  • 3,144
  • 4
  • 24
  • 32
  • Nope. adj_mat is an ARRAY OF ARRAYS. adj_mat[1] is still a char *, not a char. –  Apr 28 '12 at 18:12