Newbie-Question: Function-Parameters

M

merman

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
 
D

dandelion

merman said:
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.
 
P

Pedro Graca

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

[newbie answer]
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;
}
 
E

Eric Sosman

merman said:
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.
 
J

John Bode

merman said:
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.
 
Z

Zian Smith

dandelion said:
merman said:
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
 
P

pete

Eric said:
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.
 
M

Mabden

pete said:
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.
 
D

dandelion

Zian Smith said:
"dandelion" <[email protected]> wrote in message
merman said:
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.
 
J

John Bode

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;
}
 
D

dandelion

John Bode said:
(e-mail address removed) (John Bode) wrote in message
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.
 

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,774
Messages
2,569,599
Members
45,169
Latest member
ArturoOlne
Top