question on passing char ** to fn

E

Eric

Here is what i am trying to do:

void fn(char **a_list);
int main(void)
{
char list[6][32];

fn(list);
printf("list 0 %s\n", list[0]);
printf("list 1 %s\n", list[1]);
printf("list 2 %s\n", list[2]);
}
void fn(char **a_list)
{
strcpy(a_list[0], "one");
strcpy(a_list[1], "two");
strcpy(a_list[2], "three");
}

How do i do this correctly?
I'm not sure how to declare it in the fn prototype or how to
pass the list to fn.
Can someone set me straight here on how this should be done?
Thanks
Eric
 
M

Michael Foukarakis

Here is what i am trying to do:

void fn(char **a_list);
int main(void)
{
char list[6][32];

    fn(&list);
    printf("list 0 %s\n", list[0]);
    printf("list 1 %s\n", list[1]);
    printf("list 2 %s\n", list[2]);}

void fn(char ***a_list)
{
    strcpy(a_list[0], "one");
    strcpy(a_list[1], "two");
    strcpy(a_list[2], "three");

}

Fixed. The root of your problem: function arguments in C are supplied
by value. To simulate passing by reference, use pointers.
 
E

Eric

Michael said:
Here is what i am trying to do:

void fn(char **a_list);
int main(void)
{
char list[6][32];

fn(&list);
printf("list 0 %s\n", list[0]);
printf("list 1 %s\n", list[1]);
printf("list 2 %s\n", list[2]);}

void fn(char ***a_list)
{
strcpy(a_list[0], "one");
strcpy(a_list[1], "two");
strcpy(a_list[2], "three");

}

Fixed. The root of your problem: function arguments in C are supplied
by value. To simulate passing by reference, use pointers.

Thanks for the help but that doesnt work.
I get lots of compiler warnings and it segfaults when run
I did get this to work tho (after referring to Ike Naar's response), but is
there a way to avoid the cast and still not get any warnings? I'm using gcc
4.4.1 under linux if it matters.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void fn(char a_list[][32]);

int main(void)
{
char list[6][32];

fn((char (*)[32])&list);
printf("list 0 %s\n", list[0]);
printf("list 1 %s\n", list[1]);
printf("list 2 %s\n", list[2]);
return 0;
}

void fn(char a_list[][32])
{
strcpy(a_list[0], "one");
strcpy(a_list[1], "two");
strcpy(a_list[2], "three");

}
 
I

Ike Naar

I get lots of compiler warnings and it segfaults when run
I did get this to work tho (after referring to Ike Naar's response), but is
there a way to avoid the cast and still not get any warnings? I'm using gcc
4.4.1 under linux if it matters.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void fn(char a_list[][32]);

int main(void)
{
char list[6][32];

fn((char (*)[32])&list);
printf("list 0 %s\n", list[0]);
printf("list 1 %s\n", list[1]);
printf("list 2 %s\n", list[2]);
return 0;
}

void fn(char a_list[][32])
{
strcpy(a_list[0], "one");
strcpy(a_list[1], "two");
strcpy(a_list[2], "three");

}

You don't need the cast; calling fn as

fn(list);

should work fine.
 
B

bartc

Eric said:
Here is what i am trying to do:

void fn(char **a_list);
int main(void)
{
char list[6][32];

fn(list);
printf("list 0 %s\n", list[0]);
printf("list 1 %s\n", list[1]);
printf("list 2 %s\n", list[2]);
}
void fn(char **a_list)
{
strcpy(a_list[0], "one");
strcpy(a_list[1], "two");
strcpy(a_list[2], "three");
}

How do i do this correctly?
I'm not sure how to declare it in the fn prototype or how to
pass the list to fn.
Can someone set me straight here on how this should be done?

Here's another approach using typedef to create an intermediate 'type'. I
found using what is apparently a one-dimensional array makes it easier to
code:

#include <stdio.h>
#include <string.h>

typedef char str32[32];

void fn(str32 *a_list);
int main(void)
{
str32 list[6];

fn(list);
printf("list 0 %s\n", list[0]);
printf("list 1 %s\n", list[1]);
printf("list 2 %s\n", list[2]);
}

void fn(str32 *a_list)
{
strcpy(a_list[0], "one");
strcpy(a_list[1], "two");
strcpy(a_list[2], "three");
}
 
E

Eric

Ike said:
I get lots of compiler warnings and it segfaults when run
I did get this to work tho (after referring to Ike Naar's response), but
is there a way to avoid the cast and still not get any warnings? I'm using
gcc 4.4.1 under linux if it matters.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void fn(char a_list[][32]);

int main(void)
{
char list[6][32];

fn((char (*)[32])&list);
printf("list 0 %s\n", list[0]);
printf("list 1 %s\n", list[1]);
printf("list 2 %s\n", list[2]);
return 0;
}

void fn(char a_list[][32])
{
strcpy(a_list[0], "one");
strcpy(a_list[1], "two");
strcpy(a_list[2], "three");

}

You don't need the cast; calling fn as

fn(list);

should work fine.
Without the cast this is the result:
gcc -O0 testp.c -o testp
testp.c: In function ‘main’:
testp.c:11: warning: passing argument 1 of ‘fn’ from incompatible pointer
type
testp.c:5: note: expected ‘char (*)[32]’ but argument is of type ‘char (*)
[6][32]’

Here is the source:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void fn(char a_list[][32]);

int main(void)
{
char list[6][32];

fn(&list);
printf("list 0 %s\n", list[0]);
printf("list 1 %s\n", list[1]);
printf("list 2 %s\n", list[2]);
return 0;
}

void fn(char a_list[][32])
{
strcpy(a_list[0], "one");
strcpy(a_list[1], "two");
strcpy(a_list[2], "three");

}


Thanks
Eric
 
B

Barry Schwarz

If you are not going to read the responses for details, you won't get
very far in programming. There is no & in Ike's call to fn. Why is
there one in yours?

Ike said:
I get lots of compiler warnings and it segfaults when run
I did get this to work tho (after referring to Ike Naar's response), but
is there a way to avoid the cast and still not get any warnings? I'm using
gcc 4.4.1 under linux if it matters.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void fn(char a_list[][32]);

int main(void)
{
char list[6][32];

fn((char (*)[32])&list);
printf("list 0 %s\n", list[0]);
printf("list 1 %s\n", list[1]);
printf("list 2 %s\n", list[2]);
return 0;
}

void fn(char a_list[][32])
{
strcpy(a_list[0], "one");
strcpy(a_list[1], "two");
strcpy(a_list[2], "three");

}

You don't need the cast; calling fn as

fn(list);

should work fine.
Without the cast this is the result:
gcc -O0 testp.c -o testp
testp.c: In function ‘main’:
testp.c:11: warning: passing argument 1 of ‘fn’ from incompatible pointer
type
testp.c:5: note: expected ‘char (*)[32]’ but argument is of type ‘char (*)
[6][32]’

Here is the source:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void fn(char a_list[][32]);

int main(void)
{
char list[6][32];

fn(&list);
printf("list 0 %s\n", list[0]);
printf("list 1 %s\n", list[1]);
printf("list 2 %s\n", list[2]);
return 0;
}

void fn(char a_list[][32])
{
strcpy(a_list[0], "one");
strcpy(a_list[1], "two");
strcpy(a_list[2], "three");

}


Thanks
Eric
 
B

Ben Bacarisse

Malcolm McLean said:
Eric said:
char list[6][32];

void fn(char **a_list)
How do i do this correctly?
Multi-dimensional arrays in C are implemented very poorly. They work as
expected as long as the array is in scope, but as soon as you try to pass to
a subroutine, you find ypurself immeshed in difficulties and stupid
syntax.

This is not true in C99 which might be available to the OP. I think
C99's syntax for passing variably modified array types is reasonable.
At least, I think it is unreasonable to call the syntax stupid.
The reason for the problem is that a multi-dimensional array is just a
contiguous area of memeory. It carries no size information with it. So a
subroutine doesn't know the x-dimension of the array, unless you tell it. If
you tell it, you can only pass arrays with an xdimension of precisely the
number ypu specify, which makes subroutines useless for most
purposes.

If I understand this, one part is correct. To the OP: you need to
pass a size or sizes so the function knows how big the array is. The
other part, about arrays not carrying any size information is not
true, particularly in C99 where a variable size can be specified.
You can semi-solve the problem by creating a multidimensional array which
consists of a list of pointers (eg a char **). However you then can't use
"flat" multi-dimensional arrays, and arrays of pointers are a nuisance to
intialise.

Most experienced C programmers simply use flat arrays and do the
calculations by hand (index = y * width + x). This isn't ideal, but it
works, and gets round the syntax and interfacing problems.

If circumstances permit, I'd use C99 and pass in the sizes. The
result is reasonably clear.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top