Passing an array to a function

L

Lars Erdmann

Hallo,

I don't know all the subtleties of the C language, therefore if I have
something like the code below:

1.) is it assured for all C compilers that the "function" will always
work on the memory space occupied by array type variable "myArray" or is
it possible for some compilers that it might work on a stack copy of
"myArray" (and therefore "function" would not change the contents of
variable "myArray" but only the stack copy) ?

2.) equivalently, is it assured for all C compilers that the address of
"myArray" will be passed to "function" instead of the whole contents of
"myArray" be copied into the stack ?


Lars



#include <stdio.h>

typedef unsigned long TULONGArray10[10];

void function(TULONGArray10 a)
{
printf("Adress of array variable in function:%#p\n",(void *)a);

printf("In function call:\n");
{
unsigned long i;
for(i=0;i<10;i++)
{
a = i;
printf("a[%lu] = %lu\n",i,a);
}
}
return;
}

int main(int argc,char *argv[])
{
TULONGArray10 myArray={0};

printf("Adress of array variable in main:%#p\n",(void *)myArray);

printf("Before function call:\n");
{
unsigned long i;
for (i=0;i<10;i++)
{
printf("a[%lu] = %lu\n",i,myArray);
}
}

function(myArray);

printf("After function call:\n");
{
unsigned long i;
for (i=0;i<10;i++)
{
printf("a[%lu] = %lu\n",i,myArray);
}
}
return 0;
}
 
L

Lars Erdmann

Eric said:
Yes and yes. See Question 6.4 in the comp.lang.c Frequently
Asked Questions (FAQ) list at <http://www.c-faq.com/>, and don't
forget to follow the links in the answer. (It would probably do
you good to read the rest of Section 6, too -- and the rest of
the FAQ has information you might someday find useful ...)
Thanks for the quick answer and the url.

Lars
 
K

kid joe

Lars said:
I don't know all the subtleties of the C language, therefore if I have
something like the code below:

1.) is it assured for all C compilers that the "function" will always
work on the memory space occupied by array type variable "myArray" or is
it possible for some compilers that it might work on a stack copy of
"myArray" (and therefore "function" would not change the contents of
variable "myArray" but only the stack copy) ?

2.) equivalently, is it assured for all C compilers that the address of
"myArray" will be passed to "function" instead of the whole contents of
"myArray" be copied into the stack ?

Yes, because

void f( int a [10] ) { /* ... */ }

really declares and defines a function equivalent to

void f( int* a ) { /* ... */ }

In other words, this is valid:

void f( int a [10] );
void f( int* a ) { /* ... */ }

and so is this:

void f( int a [10] );
void f( int a [20] ) { /* ... */ }

And of course at the caller site, attempting to pass an array will cause
an implicit conversion into a pointer to the first element:

void user()
{
int u10 [10];
int u20 [20];
int* u = malloc( 30 * sizeof *u );
f( u10 ); /* equivalent to f( &u[0] ); */
f( u20 ); /* OK */
f( u ); /* OK */
}

And sorry for shooting my mouth (hands) off, as this is assuredly in the
C FAQ: http://www.it.usyd.edu.au/~dasymond/mirror/c-faq/aryptr/index.html

Hi blargg,

I believe since C99 you can also use the static keyword to indicate that a
function parameter really is an array of a given size not just any old
pointer, eg

my_function(static int a[10]); // not equivalent to my_function(int *a);

Cheers,
Joe
 
K

Keith Thompson

kid joe said:
I believe since C99 you can also use the static keyword to indicate that a
function parameter really is an array of a given size not just any old
pointer, eg

my_function(static int a[10]); // not equivalent to my_function(int *a);

Not quite. The syntax is:

void my_function(int param[static 10]);

The parameter is still adjusted to a pointer, but the argument must
point to the first element of an array of at least 10 elements. If it
doesn't, the behavior is undefined. So for this particular usage, the
"static 10" does nothing other than creating undefined behavior for
certain calls. I think it's intended to allow for optimization; a
conforming compiler could just ignore it.

C99 6.7.5.3p7:

A declaration of a parameter as ``array of type'' shall be
adjusted to ``qualified pointer to type'', where the type
qualifiers (if any) are those specified within the [ and ] of the
array type derivation. If the keyword static also appears within
the [ and ] of the array type derivation, then for each call to
the function, the value of the corresponding actual argument shall
provide access to the first element of an array with at least as
many elements as specified by the size expression.
 
P

Phil Carmody

Keith Thompson said:
kid joe said:
I believe since C99 you can also use the static keyword to indicate that a
function parameter really is an array of a given size not just any old
pointer, eg

my_function(static int a[10]); // not equivalent to my_function(int *a);

Not quite. The syntax is:

void my_function(int param[static 10]);

The parameter is still adjusted to a pointer, but the argument must
point to the first element of an array of at least 10 elements. If it
doesn't, the behavior is undefined. So for this particular usage, the
"static 10" does nothing other than creating undefined behavior for
certain calls. I think it's intended to allow for optimization; a
conforming compiler could just ignore it.

C99 6.7.5.3p7:

A declaration of a parameter as ``array of type'' shall be
adjusted to ``qualified pointer to type'', where the type
qualifiers (if any) are those specified within the [ and ] of the
array type derivation. If the keyword static also appears within
the [ and ] of the array type derivation, then for each call to
the function, the value of the corresponding actual argument shall
provide access to the first element of an array with at least as
many elements as specified by the size expression.


Are sub-arrays considered to be arrays? They have all the properties
that arrays do, as far as I can think currently, and therefore, if
they quack like arrays, I would presume that they would in fact be
arrays.

Basically, I'd like this to be valid:

extern void insertName(char[static 10]);
char banner[80];
#define NAME_OFFSET 69
insertName(banner+NAME_OFFSET);

Phil
 
P

Phil Carmody

Keith Thompson wrote:
[...]
void my_function(int param[static 10]);

The parameter is still adjusted to a pointer, but the argument must
point to the first element of an array of at least 10 elements. If it
doesn't, the behavior is undefined. So for this particular usage, the
"static 10" does nothing other than creating undefined behavior for
certain calls. I think it's intended to allow for optimization; a
conforming compiler could just ignore it.

C99 6.7.5.3p7:

A declaration of a parameter as ``array of type'' shall be
adjusted to ``qualified pointer to type'', where the type
qualifiers (if any) are those specified within the [ and ] of the
array type derivation. If the keyword static also appears within
the [ and ] of the array type derivation, then for each call to
the function, the value of the corresponding actual argument shall
provide access to the first element of an array with at least as
many elements as specified by the size expression.

And the point of this is? That is, what advantage does

void f( int a [static 10] )
{
/* use a in various ways */
}

have over

void f( int a [10] )
{
a [9]; // tell compiler that array is at least 10 elements
/* use a in various ways */
}

Given that neither of those is a call to the function, methink's
you've missed the point.
? In either case, a compiler can know to do run-time checking to ensure a
really does point to an array of at least 10 elements.

Not necessarily - the above won't even necessarily be visible to
the compiler where the questionable calls are found.

Phil
 
K

Keith Thompson

Phil Carmody said:
C99 6.7.5.3p7:

A declaration of a parameter as ``array of type'' shall be
adjusted to ``qualified pointer to type'', where the type
qualifiers (if any) are those specified within the [ and ] of the
array type derivation. If the keyword static also appears within
the [ and ] of the array type derivation, then for each call to
the function, the value of the corresponding actual argument shall
provide access to the first element of an array with at least as
many elements as specified by the size expression.


Are sub-arrays considered to be arrays? They have all the properties
that arrays do, as far as I can think currently, and therefore, if
they quack like arrays, I would presume that they would in fact be
arrays.

I believe so, yes. I don't have chapter and verse to prove it;
perhaps someone else can track it down.
Basically, I'd like this to be valid:

extern void insertName(char[static 10]);
char banner[80];
#define NAME_OFFSET 69
insertName(banner+NAME_OFFSET);

That should be ok.
 
P

Phil Carmody

Keith Thompson said:
Phil Carmody said:
C99 6.7.5.3p7:

A declaration of a parameter as ``array of type'' shall be
adjusted to ``qualified pointer to type'', where the type
qualifiers (if any) are those specified within the [ and ] of the
array type derivation. If the keyword static also appears within
the [ and ] of the array type derivation, then for each call to
the function, the value of the corresponding actual argument shall
provide access to the first element of an array with at least as
many elements as specified by the size expression.


Are sub-arrays considered to be arrays? They have all the properties
that arrays do, as far as I can think currently, and therefore, if
they quack like arrays, I would presume that they would in fact be
arrays.

I believe so, yes. I don't have chapter and verse to prove it;
perhaps someone else can track it down.
Basically, I'd like this to be valid:

extern void insertName(char[static 10]);
char banner[80];
#define NAME_OFFSET 69
insertName(banner+NAME_OFFSET);

That should be ok.


Good good. I just had that worryingly anal 'what if we try to
misinterpret it' feeling. When I asked it was early morning,
and I wasn't in a fit state to pedantically pick apart the
standard.

However, as it's now very late at night, nothing will calm
my mind like a standards-approved "no problem, see x.y.z".

Cheers,
Phil
 
T

Tim Rentsch

Keith Thompson wrote:
[...]
void my_function(int param[static 10]);

The parameter is still adjusted to a pointer, but the argument must
point to the first element of an array of at least 10 elements. If it
doesn't, the behavior is undefined. So for this particular usage, the
"static 10" does nothing other than creating undefined behavior for
certain calls. I think it's intended to allow for optimization; a
conforming compiler could just ignore it.

C99 6.7.5.3p7:

A declaration of a parameter as ``array of type'' shall be
adjusted to ``qualified pointer to type'', where the type
qualifiers (if any) are those specified within the [ and ] of the
array type derivation. If the keyword static also appears within
the [ and ] of the array type derivation, then for each call to
the function, the value of the corresponding actual argument shall
provide access to the first element of an array with at least as
many elements as specified by the size expression.

And the point of this is? That is, what advantage does

void f( int a [static 10] )
{
/* use a in various ways */
}

have over

void f( int a [10] )
{
a [9]; // tell compiler that array is at least 10 elements
/* use a in various ways */
}

? In either case, a compiler can know to do run-time checking to ensure a
really does point to an array of at least 10 elements.

Only the first form can be used in a function prototype,
which allows the possibility of compile-time checking
at call sites.
 
T

Tim Rentsch

Keith Thompson said:
Phil Carmody said:
C99 6.7.5.3p7:

A declaration of a parameter as ``array of type'' shall be
adjusted to ``qualified pointer to type'', where the type
qualifiers (if any) are those specified within the [ and ] of the
array type derivation. If the keyword static also appears within
the [ and ] of the array type derivation, then for each call to
the function, the value of the corresponding actual argument shall
provide access to the first element of an array with at least as
many elements as specified by the size expression.


Are sub-arrays considered to be arrays? They have all the properties
that arrays do, as far as I can think currently, and therefore, if
they quack like arrays, I would presume that they would in fact be
arrays.

I believe so, yes. I don't have chapter and verse to prove it;
perhaps someone else can track it down.

As a practical matter, I agree that it's nearly inconceivable that it
wouldn't work, but the question does seem arguable given the existing
wording about "first element of an array" etc. If a[] is an array
(with at least 11 elements), I don't know of any provision in the
Standard that says a+1 is the /first/ element of some array.

Also, consider this:

int *p = malloc( 20 * sizeof *p );
int (*q)[5] = (void*) p;
extern void foo( int [static 10] );
foo( p+1 );
foo( q[0]+1 );

If 'foo( p+1 )' is legal, does that mean 'foo( q[0]+1 )'
is also legal? Both "provide access to the first element
of an array with at least as many elements as specified by
the size expression."
 
K

Keith Thompson

Tim Rentsch said:
(e-mail address removed) (blargg) writes: [...]
And the point of this is? That is, what advantage does

void f( int a [static 10] )
{
/* use a in various ways */
}

have over

void f( int a [10] )
{
a [9]; // tell compiler that array is at least 10 elements
/* use a in various ways */
}

? In either case, a compiler can know to do run-time checking to ensure a
really does point to an array of at least 10 elements.

Only the first form can be used in a function prototype,
which allows the possibility of compile-time checking
at call sites.

Both ``void f( int a [static 10] )'' and ``void f( int a [10] )'' are
prototypes. The second one just doesn't really specify the size of
the array. (And the first doesn't *require* compile-time checking.)
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
(e-mail address removed) (blargg) writes: [...]
And the point of this is? That is, what advantage does

void f( int a [static 10] )
{
/* use a in various ways */
}

have over

void f( int a [10] )
{
a [9]; // tell compiler that array is at least 10 elements
/* use a in various ways */
}

? In either case, a compiler can know to do run-time checking to ensure a
really does point to an array of at least 10 elements.

Only the first form can be used in a function prototype,
which allows the possibility of compile-time checking
at call sites.

Both ``void f( int a [static 10] )'' and ``void f( int a [10] )'' are
prototypes. The second one just doesn't really specify the size of
the array. (And the first doesn't *require* compile-time checking.)

Yes, that's what I meant, although it was said poorly. For "the
second form" I meant the whole definition including the 'a[9]' in
the function body, which cannot be put into a prototype.
 

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,586
Members
45,096
Latest member
ThurmanCre

Latest Threads

Top