# Newbie-Question: Function-Parameters

Discussion in 'C Programming' started by merman, Oct 7, 2004.

1. ### mermanGuest

Hi,

What is the most common way to pass an array into a function - and how
can I return it?

Thanks for help.

o-o

Thomas

merman, Oct 7, 2004

2. ### dandelionGuest

"merman" <> wrote in message
news:416556a4\$0\$168\$...
> Hi,
>
> What is the most common way to pass an array into a function - and how
> can I return it?

By pointer, which is even simpler than you may think. you could call

void foobar(int bla[])
{

}

or

void foobar( int* bla)
{

}

using

int barfoo[3] = { 1, 2, 3 };
foobar(barfoo);

The two forms of function foobar are (more or less) equivalent. the sole
identifier 'barfoo' (as opposed to barfoo[2]) evaluates to a pointer to the
array.

See? Easy.

dandelion, Oct 7, 2004

3. ### Pedro GracaGuest

merman wrote:
> What is the most common way to pass an array into a function - and how
> can I return it?

pass a pointer and the array size, example:

#include <stdio.h>

void reverse_array(int * array, const size_t n) {
size_t i;
int tmp;

for (i=0; i<n/2; ++i) {
tmp = array;
array = array[(n-1)-i];
array[(n-1)-i] = tmp;
}
}

int main(void) {
int arr3[3] = {7, 8, 9};
int arr6[6] = {2, 3, 4, 5, 6, 7};
size_t i;

reverse_array(arr3, 3);
reverse_array(arr6, 6);

printf("arr3: ");
for (i=0; i<3; ++i) printf("%d ", arr3);
printf("\n\n");

printf("arr6: ");
for (i=0; i<6; ++i) printf("%d ", arr6);
printf("\n\n");

return 0;
}

--
USENET would be a better place if everybody read: | to mail me: |
http://www.catb.org/~esr/faqs/smart-questions.html | simply "reply" |
http://www.netmeister.org/news/learn2quote2.html | with text-only, |
http://www.expita.com/nomime.html | no attachments. |

Pedro Graca, Oct 7, 2004
4. ### Eric SosmanGuest

merman wrote:
> Hi,
>
> What is the most common way to pass an array into a function - and how
> can I return it?

Strictly speaking, neither is possible. When we
speak of "passing an array to a function" or "returning
an array from a function," we're using sloppy language.
Sloppy, but convenient: it's easier to say "This function
returns a string" than to say "This function returns a
pointer to the first character of a string."

Recommended reading: Section 6 of the comp.lang.c
Frequently Asked Questions (FAQ) list

http://www.eskimo.com/~scs/C-faq/top.html

.... with special attention to Question 6.4.

If you really, truly must pass arrays to and from
functions, you'll need to "disguise" them inside some
other kind of object, usually a `struct'. But this is
very seldom what you actually need to do; think carefully
before trying it.

--

Eric Sosman, Oct 7, 2004
5. ### Michael MairGuest

Michael Mair, Oct 7, 2004
6. ### mermanGuest

Thanks for help - It's a really good group;-).

o-o

Thomas

merman, Oct 7, 2004
7. ### John BodeGuest

merman <> wrote in message news:<416556a4\$0\$168\$>...
> Hi,
>
> What is the most common way to pass an array into a function - and how
> can I return it?
>
> Thanks for help.
>
> o-o
>
> Thomas

Strictly speaking, you can't pass array type objects as function
parameters. What you can do is either pass a pointer to the first
element in the array, or a pointer to the array object as a whole.
The former is more common:

#define ARRSIZE 10

void process_arr(int *arr, size_t arrsize)
{
size_t i;
for (i = 0; i < arrsize; i++)
{
arr = i * 2;
}
}

int main(void)
{
int arr[ARRSIZE];

process_arr (arr, sizeof arr); /* in this context, arr == &arr[0]
*/
return 0;
}

Since you can't determine the size of the array based on a pointer to
the first element, you must somehow specify the array size separately,
either by passing the array size as a separate parameter (as above),
or by writing a sentinel value to the array:

#include <stdio.h>

void print_names(char **names)
{
size_t i = 0;

while (names != NULL)
{
printf ("name = %s\n", names[i++]);
}
}

int main(void)
{
char *names[4] = {"Joe", "Bob", "Sue", NULL};

print_names(names);
return 0;
}

Note that most of the string processing library functions (strcmp(),
strcat(), etc.) use the sentinel value method (i.e., the terminating 0
in a character array) to determine the length of the strings passed to
them. However, as anyone who's been bitten by gets() knows, this is
not the most robust method for determining the physical size of an
array. When I write array processing functions, I rely on passing the
array size as a separate parameter.

You can also pass a pointer to the array object (as opposed to a
pointer to the first element):

void process_arr(int (*arr)[ARRSIZE])
{
size_t i;

for (i = 0; i < sizeof *arr; i++)
{
(*arr) = i*2;
}
}

int main(void)
{
int a[ARRSIZE];

process_arr(&a);
return 0;
}

This form isn't used as much, largely because it isn't as flexible.
The first method allows functions to work with arrays of any size,
whereas this method only allows functions to work with arrays of a
specific size. Doesn't help that the syntax is a little uglier.
However, there are times when it is the right thing to use.

Just as you cannot pass an array as an argument directly, you cannot
have a function return an array type. You must either return a
pointer to the first element, or a pointer to the whole array object.

#include <stdlib.h>

int *init_arr(void)
{
static int arr[ARRSIZE];
size_t i;
for (i = 0; i < sizeof arr; i++)
{
arr = i * 2;
}
return arr; /* again, in this context, arr == &arr[0] */
}

int (*init_fixedarr())[ARRSIZE]
{
static int arr[ARRSIZE];
size_t i;
for (i = 0; i < sizeof arr; i++)
{
arr = i * 2;
}
return &arr;
}

int main (void)
{
int *a1;
int (*a2)[ARRSIZE];

a1 = init_arr();
a2 = init_fixedarr();

return 0;
}

Since returning auto variables is a Bad Idea, I had to declare the
arrays as static. Normally you won't be returning pointers to static
array objects, but rather allocating memory on the fly and returning
pointers to that:

int *new_arr(size_t size)
{
int *a = malloc (size * sizeof *a);
if (!a)
{
/* handle or log memory error */
}
return a;
}

int (*new_fixedarr())[ARRSIZE]
{
int (*a)[ARRSIZE] = malloc (sizeof *a);
if (!a)
{
/* handle or log memory error */
}
return a;
}

Note that, in these cases, a1 will *not* be an object of array type,
and you will not be able to determine its physical size without
somehow returning or logging the array size as a separate value.

John Bode, Oct 7, 2004
8. ### Zian SmithGuest

"dandelion" <> wrote in message news:<416559ff\$0\$147\$4all.nl>...
> "merman" <> wrote in message
> news:416556a4\$0\$168\$...
> > Hi,
> >
> > What is the most common way to pass an array into a function - and how
> > can I return it?

>
> By pointer, which is even simpler than you may think. you could call
>
> void foobar(int bla[])
> {
>
> }
>
> or
>
> void foobar( int* bla)
> {
>
> }
>
> using
>

<snip>

Don't forget to pass the length of the array to the function..

void foobar(int bla[], size_t len)
{

}

-Z.Smith

Zian Smith, Oct 7, 2004
9. ### peteGuest

Eric Sosman wrote:
>
> merman wrote:
> > Hi,
> >
> > What is the most common way to pass an array into a function - and how
> > can I return it?

>
> Strictly speaking, neither is possible. When we
> speak of "passing an array to a function" or "returning
> an array from a function," we're using sloppy language.
> Sloppy, but convenient: it's easier to say "This function
> returns a string" than to say "This function returns a
> pointer to the first character of a string."

You could say that it returns a pointer to a string.
The term "pointer to a string" is defined in N869.

--
pete

pete, Oct 8, 2004
10. ### MabdenGuest

"pete" <> wrote in message
news:...
> Eric Sosman wrote:
> >
> > When we
> > speak of "passing an array to a function" or "returning
> > an array from a function," we're using sloppy language.
> > Sloppy, but convenient: it's easier to say "This function
> > returns a string" than to say "This function returns a
> > pointer to the first character of a string."

>
> You could say that it returns a pointer to a string.
> The term "pointer to a string" is defined in N869.

Oh. OK, thanks, we'll all do that from now on.

--
Mabden

Mabden, Oct 8, 2004
11. ### dandelionGuest

"Zian Smith" <> wrote in message
news:...
> "dandelion" <> wrote in message

news:<416559ff\$0\$147\$4all.nl>...
> > "merman" <> wrote in message
> > news:416556a4\$0\$168\$...
> > > Hi,
> > >
> > > What is the most common way to pass an array into a function - and how
> > > can I return it?

> >
> > By pointer, which is even simpler than you may think. you could call
> >
> > void foobar(int bla[])
> > {
> >
> > }
> >
> > or
> >
> > void foobar( int* bla)
> > {
> >
> > }
> >
> > using
> >

> <snip>
>
> Don't forget to pass the length of the array to the function..
>
> void foobar(int bla[], size_t len)
> {
>
> }

good hint, but only if it's not known in advance by

#define FOOBAR_BUFFER_SIZE

or simular.
>
> -Z.Smith

dandelion, Oct 8, 2004
12. ### John BodeGuest

(John Bode) wrote in message news:<>...
> process_arr (arr, sizeof arr); /* in this context, arr == &arr[0]
> */

Well that was sloppy. What I *meant* to say was that when an array
identifier appears in an expression, the type of the identifier is
converted from "array of T" to "pointer to T", and it's value is the
address of the first element in the array, *except* when the array
identifier is an operand to either sizeof or &, so:

sizeof arr -- type of arr == ARRSIZE-element array of int
&arr -- type of arr == ARRSIZE-element array of int
arr -- type of arr == pointer to int, value == &arr[0]

And someone else mentioned another way to pass arrays to functions; as
members of a struct type:

struct s {
int arr[10];
};

void process_arr(struct s *arg)
{
size_t i;
for (i = 0; i < sizeof arg->arr; i++)
{
/* do something interesting with arg->arr */
}
}

int main(void)
{
struct s foo;

process_arr (&foo);
return 0;
}

John Bode, Oct 8, 2004
13. ### John BodeGuest

(John Bode) wrote in message news:<>...

> int (*new_fixedarr())[ARRSIZE]

....and that *should* be

int (*new_fixedarr(void))[ARRSIZE]

Gah. Should stop trying to post, test, write code, and read email all
at the same time.

John Bode, Oct 8, 2004
14. ### dandelionGuest

"John Bode" <> wrote in message
news:...
> (John Bode) wrote in message

news:<>...
>
> > int (*new_fixedarr())[ARRSIZE]

>
> ...and that *should* be
>
> int (*new_fixedarr(void))[ARRSIZE]
>
>
> Gah. Should stop trying to post, test, write code, and read email all
> at the same time.

Never mind...

I once cancelled a message 4 times before getting it right. Admittedly that
ws prolog, but the idea is the same.

dandelion, Oct 11, 2004