Malcolm Nooning <> writes:
> I am very close. The code pasted further below prints out
> maintable is not NULL.
> A01 A02 A03 A04
> Segmentation fault (core dumped)
> I know the problem has to do with pointer indirection, but I cannot
> reason (or guess) it out. Where is the bug?
There is not really one bug more a general misunderstanding about how a
function can alter a variable in the calling function and another
misunderstanding about the distinction between arrays and pointers.
Specifically about pointers to pointers and 2D arrays. I think you'd
find Q6.18 of the C FAQ useful:
http://c-faq.com/aryptr/pass2dary.html
> ------- Paste of updated code snippet
>
> #include <stdio.h>
>
> void print_table (char ***);
> void get_table (char ***);
>
> int main (void) {
> char ***maintable;
> get_table(maintable);
A C function can not alter in any way the value of it argument.
get_table can't change maintable no matter how many *s the declaration
has.
Step back a bit and think about a function that takes an int:
void f(int);
and a call to it like this:
int x = 42;
f(42);
we know for certain that f can't change x -- C passes by value: the
value of x is passed to f and appears in f as the initial value of a new
object, the declared parameter of the function.
It won't matter if add a star:
void f(int *);
/* ... */
int *x;
f(x);
or if we add several:
void f(int ****);
/* ... */
int ****x;
f(x);
the function can't change x. For a function to change something in the
calling function we must pass a pointer to that thing. This means that
the declaration of the function's parameter will have one more * than
the declaration of object we want changed. This mismatch is corrected
but passing &x rather than x:
void f(int *ip) { *ip = 1; }
/* ... */
int x = 42;
f(&x);
Now x will be 1.
> if (maintable == NULL) {
> puts("maintable is NULL.");
> } else {
> puts("maintable is not NULL.");
> print_table(maintable);
The fact that you get this is simply an accident.
> }
> }
>
> void get_table (char ***table) {
> static char *functable[2][4] =
> {
> "A01", "A02", "A03", "A04",
> "B01", "B02", "B03", "B04"
> };
> *table = functable;
If the compiler is not complaining about this line, you must alter the
way you call it. The assignment is between type that can't be assigned
without a diagnostic (basically an error message). The expression
functable
is of type char *(*)[4]. That's quite a complex type (it's a pointer to
an array or 4 pointers to char) but the point is that you can't assign
such an object to a char ** object (that's the type of *table).
Arrays complicate the picture to the extent that I am not exactly sure
how best to fix things. If you really need to have the function alter an
object in the caller so that it refers to a 2D array of strings then
you'll need a seriously complex type![1]
If you said what it is you need to do, maybe someone could come up with
a simpler design.
> }
>
> void print_table (char ***ptable) {
> int i, j, k;
> for (i=0; i < 2; i++) {
> for (j=0; j < 4; j++) {
> for (k=0; k < 3; k++) {
> printf("%c", ptable[i][j][k]);
> }
> printf(" ");
> }
> printf("\n");
> }
> };
That ; is a syntax error.
[1] Here's one way:
#include <stdio.h>
void print_table (char *(*)[4]);
void get_table (char *(**)[4]);
int main (void) {
char *(*maintable)[4];
get_table(&maintable);
if (maintable == NULL) {
puts("maintable is NULL.");
} else {
puts("maintable is not NULL.");
print_table(maintable);
}
}
void get_table (char *(**table)[4]) {
static char *functable[2][4] =
{
"A01", "A02", "A03", "A04",
"B01", "B02", "B03", "B04"
};
*table = functable;
}
void print_table (char *(*ptable)[4]) {
int i, j, k;
for (i=0; i < 2; i++) {
for (j=0; j < 4; j++) {
for (k=0; k < 3; k++) {
printf("%c", ptable[i][j][k]);
}
printf(" ");
}
printf("\n");
}
}
but I doubt very much that this is the best way to do what you want.
--
Ben.