Hi all,
I need to enter the discussion here, because too many wrong things have been
written regarding this topic in the last messages, and some clarifications
from a compiler writer may be usefull.
Arguments in C are not types, neither objects or variables; arguments are
expressions, and the only way to pass the result of an expression is to copy
it on the stack (physical or simulated, whatever). It means that any C
simple object beeing copied, it is passed by value, then meaning that any
attempt to modify such an argument inside the called function will modify a
copy on the stack, and not the original object itself.
This mechanism has to be detailed for compound objects: arrays, structures,
and functions (yes, a function is a C object).
Inside an expression, an array name is replaced by a pointer to its first
element, with the exception of the sizeof operator.
It means that the indirect '*' and index '[i]' operators can
be applied
indifferently on both arrays and pointers.
An argument beeing an expression, if you try to pass an array to a function,
the argument will be considered as a pointer to a C object, which can also
be declared as an array inside the called function, or as a pointer. This is
transparently handled by the compiler, but this behaviour has an important
consequence. By passing an address, any attempt to modify an array element
will actually modify the original array. This mechanism is then acting as
for an argument passed by address (or reference).
So passing an array is equivalent to passing a pointer. Note that in most
cases, the compiler would be in trouble guessing an array size when declared
like: 'extern int array[];', where no dimension is provided. For the
same
reason, arrays cannot be assigned; this would imply that the sizes are
always known.
This is different for structures, because they are usually completely
defined, and their size usually known by the compiler. As a first result,
structures can be assigned. This is not a pointer copy, but a full memory
copy (this may cost some code and time). So, when a structure is passed as
an argument to a function, it is actually copied completely on the stack. Of
course, this is costing code, time, and stack space, and this is why this
feature is usually avoided. It is much more efficient to pass explicitly the
address of a structure by using the '&' operator, but in such a
case, the
argument must be declared as a pointer to such a structure explicitly inside
the called function, and of course, any attempt to modify a structure field
through this pointer will modify the original structure.
Note that functions can be passed as arguments to functions, because a
function name is also equivalent to a code address. Such an argument will
have to be declared explicitly as a pointer inside the called function. The
function call operator '()' may be used indifferently on both function
names
and function pointers. You can call a function pointer by dereferencing the
pointer '(*pf)();' or directly 'pf();' as if pf was a
function.
Now, regarding the return statement, C is returning expressions, so you can
simply consider the same mechanisms for returning values. Returning an array
name will actually return a pointer to that array. Be cautious about
returning the address of a local array, as well as the address of a local
variable, because such an address may be irrelevant after the called
function has returned. The local space has probably been cleaned out from
the stack space and may be overwritten by another function call or an
interrupt.
Returning a structure will physically copy the returned structure to the
destination (usually the assigned structure), and this will cost code and
time. Unless the structure is small enough, it is more efficient to set
directly the resulting structure inside the called function by passing the
structure address as an extra argument, thus replacing 'str = fs(i);'
by
'fs(&str, i);'.
Returning a function name will physically return the function address.
Sorry to have been so long and so professoral, but I thought it was
necessary.
Best Regards,
Jean-Pierre Lavandier
COSMIC Software
-----Message d'origine-----
De : Erich Styger [mailto:]
Envoy: mardi 26 novembre 2002 06:17
:
Objet : RE: [68HC12] Re: Arrays permitted in CodeWarrior for HC12?
for C, you only can pass simple types (char, int, pointer, etc) as argument,
but no arrays or structs (you have to use pointers).
However, as return value, you can return a struct (struct-return).
myStructType foo(void) {
...
}
Erich
> -----Original Message-----
> From: Andrei Chichak [mailto:]
> Sent: Monday, November 25, 2002 5:03 PM
> To:
> Subject: Re: [68HC12] Re: Arrays permitted in CodeWarrior for HC12?
> At 03:12 PM 11/23/2002 -0800, you wrote:
> >You can pass/return a "struct" I believe, but it's not
as efficient as
> >passing/returning an address of an array (or whatever).
> >
> >GB
>
> GB! You should know better than that! C will only pass simple types,
ints,
> floats, pointers to complex types (structs,
arrays), etc. You can appear
to
> pass in a struct, but you only pass a pointer to
it. You can't pass out a
> complex type, but you can pass out a pointer to one. DON'T pass out a
> pointer to a local struct, it goes out of scope when the routine ends.
>
> Hey GB, are you doing Thanksgiving on Thursday or did you do it last
month?
>
> AC
> --------------------
> <http://www.motorola.com/mcu
> ">http://docs.yahoo.com/info/terms/
<http://docs.yahoo.com/info/terms/>
>
>
<http://rd.yahoo.com/M#7459.2675695.4055211.2225243/D=egroupweb/S065542
05:HM/A67611/R=0/*http://ad.doubleclick.net/jump/N2524.Yahoo/B1071650;sz=
300x250;ord38288019035540?>
<http://us.adserver.yahoo.com/l?M#7459.2675695.4055211.2225243/D=egroupmai
l/S=:HM/A67611/rand26365077>
--------------------
<http://www.motorola.com/mcu
">http://docs.yahoo.com/info/terms/> .
|