Passing variable size arrays by value 
Author Message
 Passing variable size arrays by value

Hi,

I known that in C arrays when passed as function parameters are
passed by reference (the pointer is really a reference to the
array). To copy a entire array during the call I have to typedef
it and pass the new type, is that ok? I was wondering how to
pass a copy of the array during the call but for variable sized
arrays (since in typedefs the size is fixed). Is it possible?

Best regards,
Rodrigo.

--
Rodrigo Augusto B. Ferreira
Computer Science Graduate, UFMG/BRAZIL
--



Mon, 03 Feb 2003 03:00:00 GMT  
 Passing variable size arrays by value


Quote:
>I known that in C arrays when passed as function parameters are
>passed by reference (the pointer is really a reference to the
>array).

This is essentially correct.  It is important to note, however,
that this is the result of the fact that the "value" of an array
is a pointer to the first element of that array.  In other words,
while the *effect* is that the parameter is "passed by reference",
this effect is *achieved* by passing &arr[0] by value.

Quote:
>To copy a entire array during the call I have to typedef
>it and pass the new type, is that ok?

The "typedef" keyword is highly misleading.  It does not define a
new type; it simply makes an alias for some already-existing type.
It has no effect whatsoever on semantics.  Thus:

        typedef int T_i_ten[10];

simply makes "T_i_ten" an alias for the existing, ordinary C type
"array 10 of int" (or "array of 10 ints", if you prefer it in that
form).  Then, since:

        int a[10];

        use(a);

passes &a[0] by value, and since typedef does not define a new type
nor change any semantics, the sequence:

        T_i_ten b;

        use(b);

has *exactly the same effect*: it passes &b[0] by value.

The only way to copy an entire array as a function parameter is not
to use an array after all.  Instead, one can embed the array within
a structure:

        struct blob {
                int a[10];
        };

Structure objects' values are -- like all other values in C -- passed
by value, so:

        struct blob x;
        ...
        use2(x);

makes a copy of "x" for use2().  (The actual copying may happen in
either the caller or the callee -- many compilers pass a pointer
to the structure, rather than the structure itself, either just
before or just after making a copy -- so it is crucial to get the
definition of use2() correct as well, in case use2() is actually
responsible for making the copy.)

Quote:
>I was wondering how to pass a copy of the array during the call
>but for variable sized arrays (since in typedefs the size is fixed).
>Is it possible?

No.  (And, as noted above, the typedef does not help, but in a
structure the size is also fixed, aside from certain inapplicable
C99 constructs.)
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc


--



Tue, 04 Feb 2003 03:00:00 GMT  
 Passing variable size arrays by value

Quote:
> I known that in C arrays when passed as function parameters are
> passed by reference (the pointer is really a reference to the
> array).

That's not quite right.  C function parameters are passed by
value.  The *name* of an array is converted to a pointer
(which is then passed by value).  If you try declaring the
parameter as an array, that declaration is adjusted to instead
declare the identifier as a pointer.

Quote:
> To copy a entire array during the call I have to typedef
> it and pass the new type, is that ok?

No, a typedef creates a synonym for an existing type; it
does not create a new type.

You can embed the array in a structure, and pass the structure
(by value).

Quote:
> I was wondering how to pass a copy of the array during the
> call but for variable sized arrays (since in typedefs the size
> is fixed). Is it possible?

C99 includes support for flexible array members of structs
and also variable-length arrays.  For C89 you have to do more
work.

I am curious why you think this is necessary?  Consider:

        void foo(type_t *a) {
                type_t my_copy_of_a[2000];
                memcpy(my_copy_of_a, a, 2000*sizeof(type_t));
                ... // work with my_copy_of_a instead of a

The fixed size 2000 could be replaced by a size parameter.
--



Tue, 04 Feb 2003 03:00:00 GMT  
 Passing variable size arrays by value

Quote:
> To copy a entire array during the call I have to typedef
> it and pass the new type, is that ok?

I don't think typedef alone will change anything, here. You'll have to
pack the array into a struct, instead. Structs are passed by-value,
i.e. they're copied. Arrays, even if hidden behind a typedef, aren't.

In C, typedef is really just syntactic sugar. It adds no special functionality
of its own.

Quote:
> I was wondering how to
> pass a copy of the array during the call but for variable sized
> arrays (since in typedefs the size is fixed). Is it possible?

I don't think so. Nor would it be advisable to do so, in most cases.
Arrays can be arbitrarily large, but the space they would have to be
copied to (stack space, on usual architectures implementing C), is
often severly limited. And copying often simply takes too long.

Therefore, it's almost always better to pass arrays by reference, and
make the copy explicitly, using malloc() and memcpy(), if and only if
needed.
--

Even if all the snow were burnt, ashes would remain.
--



Tue, 04 Feb 2003 03:00:00 GMT  
 Passing variable size arrays by value

Quote:

> I am curious why you think this is necessary?

Actually I am seeking for a way (even non-portable) to call
functions with variable parameters (...). I am writting a tool
that should make callbacks to user functions with variable
parameters, and I would prefer writting in C rather that
getting my hands dirty on assembly.

Does C99 provides a way to call variable size parameter
functions?

Thanks for all the help so far...

Best Regards,
Rodrigo.

--
Rodrigo Augusto B. Ferreira
Computer Science Graduate, UFMG/BRAZIL
--



Fri, 07 Feb 2003 03:00:00 GMT  
 Passing variable size arrays by value

Quote:
> Actually I am seeking for a way (even non-portable) to call
> functions with variable parameters (...). I am writting a tool
> that should make callbacks to user functions with variable
> parameters, and I would prefer writting in C rather that
> getting my hands dirty on assembly.

> Does C99 provides a way to call variable size parameter
> functions?

I'm not familiar with any such functionality.  In C, you can't pass
arrays by value; they must always be passed by reference (that is, by a
pointer to its first element).  But C makes it easy to do so provided
your callbacks are well-behaved; simply pass a pointer to the first
element and the length of the array, and have the callback duplicate the
array as it is needed:

    typedef int (CallbackFunction)(const Data *, size_t length);

--

 __ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
/  \ Life imitates art far more than art imitates life.
\__/ Oscar Wilde
    Interstelen / http://www.interstelen.com/
 A multiplayer, strategic, turn-based Web game on an interstellar scale.
--



Sun, 09 Feb 2003 08:38:17 GMT  
 Passing variable size arrays by value

Quote:
> Actually I am seeking for a way (even non-portable) to call
> functions with variable parameters (...). I am writting a tool
> that should make callbacks to user functions with variable
> parameters, and I would prefer writting in C rather that
> getting my hands dirty on assembly.
> Does C99 provides a way to call variable size parameter
> functions?

Sure, and so does C89.  However, what you seem to need is
*polymorphism*, i.e., to specify a pointer to a function
without being specific about the number or types of the
parameters when the function is actually invoked.  This
is possible by using an old-style function declaration:
        typedef int (*poly_func_ptr)();
        static poly_func_ptr call_this;
        void establish(poly_func_ptr callback) {
                call_this = callback;
        }
        static int int_data;
        static double dbl_data;
        void call(int kind) {
                switch (kind) {
                case INT_DBL:
                        call_this(int_data, dbl_data);
                        return;
                }
        }
etc.  The only drawback is that old-style declarations do
not support true variable-argument functions like printf.
The best solution to that is to always use a vprintf-like
function instead, which always gets passed a single
argument of type va_list instead of a variable set of
arguments.  Indeed, whenever I implement any printf-like
function it invariably turns out best if I first create
the vprintf-like function and make the other functions
invoke that one.
--



Sun, 09 Feb 2003 08:38:35 GMT  
 Passing variable size arrays by value

Quote:


> > I am curious why you think this is necessary?

> Actually I am seeking for a way (even non-portable) to call
> functions with variable parameters (...). I am writting a tool

<snip>

In that case, you are re-inventing the wheel. If you're really sure that
you need to have variable argument lists, then read the documentation
for stdarg.h which defines standard macros for handling variable
argument lists[1,p255]. Although these are on the list of major
changes[1,p1-3] to the standard, they did exist in the previous
standard.

IMVHO, however, the functionality provided by stdarg.h is somewhat
difficult to use (at least one introductory text[2] avoids the topic
entirely), and limited in that it requires you to have at least one
fixed argument[1,s7.15(2),p253]. In other words, you cannot write a
function which takes 0 or more arguments. C's support for variable
argument lists is pretty grudging (IMVHO). Admittedly they are kinda
cool and sometimes absolutely necessary, but many people (including me)
manage to avoid them _almost_ entirely.

There are a couple of examples[1,pp255-256], using these macros in
stdarg.h, in the section of the draft[1] of the new standard dealing
with va_end (7.15.1.3), and, in all likelihood, the documentation for
your system (e.g. Unix man pages, IDE online help) will provide useful.

Finally Kernighan and Ritchie provide a description[3,p155] of variable
argument lists with two examples[3,pp156,174].

HTH,

Emmet.

PS: Yes, I know it's very {*filter*} to cite the draft, but it _is_
available
    online, which is a plus, and I don't have a copy of the final cut :)

References:
1: Joint Technical Committee ISO/IEC JTC1, subcommittee 22, "WG14/N869
   Committee Draft, January 18th, 1999". Available at:
   " http://www.*-*-*.com/ ;
2: Steve Oualline, "Practical C Programming", 1st ed.; O'Reilly &
Associates,
   Sepastopol, California, 1997.
3: Brian W. Kernighan and Dennis M. Ritchie, "The C Programming
Language",
   2nd. ed.; Prentice Hall, New Jersey, 1988;
--



Sun, 09 Feb 2003 08:38:49 GMT  
 Passing variable size arrays by value

Quote:

>> I am curious why you think this is necessary?

> Actually I am seeking for a way (even non-portable) to call
> functions with variable parameters (...).
[...]
> Does C99 provides a way to call variable size parameter
> functions?

You're asking your question a bit imprecisely, it seems. Of course, C
has always offered ways to call variadic functions. How else would any
program ever have managed to call printf()?

What you do *not* get, in standard C, is a way to set up a call to a
variadic function with an unknown number or selection of arguments *at
runtime*. That's exactly why we have the vfprintf() family of
functions: to allow doing this, but in a different way.

Some compilers offer such a capability, as an extension.

--

Even if all the snow were burnt, ashes would remain.
--



Sun, 09 Feb 2003 08:40:12 GMT  
 Passing variable size arrays by value

Quote:

> In that case, you are re-inventing the wheel. If you're really sure that
> you need to have variable argument lists, then read the documentation
> for stdarg.h which defines standard macros for handling variable
> argument lists[1,p255]. Although these are on the list of major
> changes[1,p1-3] to the standard, they did exist in the previous
> standard.

What's on the list of major changes is *macros* with a variable number
of arguments (which *is* new), not functions (which is not).

-Larry Jones

All girls should be shipped to Pluto--that's what I say. -- Calvin
--



Mon, 10 Feb 2003 03:00:00 GMT  
 Passing variable size arrays by value

Quote:

> IMVHO, however, the functionality provided by stdarg.h is somewhat
> difficult to use (at least one introductory text[2] avoids the topic
> entirely), and limited in that it requires you to have at least one
> fixed argument[1,s7.15(2),p253]. In other words, you cannot write a
> function which takes 0 or more arguments. C's support for variable
> argument lists is pretty grudging (IMVHO). Admittedly they are kinda
> cool and sometimes absolutely necessary, but many people (including me)
> manage to avoid them _almost_ entirely.

The requirement for at least one non-variable argument is due to
the need in many (otherwise reasonable) implementations for an
"anchor" address to base the parameter offsets from.

The main application for variable-argument functions is for
analogues of printf, e.g. ErrLog used in the following snippet:
        if (!Validate(p)) {
                ErrLog("invalid pointer %p", p);
                return -1;
        }
--



Mon, 10 Feb 2003 03:00:00 GMT  
 Passing variable size arrays by value

Quote:

> What's on the list of major changes is *macros* with a variable number
> of arguments (which *is* new), not functions (which is not).

You are, of course, correct --- one can't get away with _anything_ in
here ;)

The addition, however, of VA_COPY 7.15.1.2 [1,p254] _is_ mentioned[1,p3]
in the list of major changes[1,p1-3] to the draft standard and in the
publically available web list[2] for the standard. This compounded my,
admittedly silly and careless, misunderstanding of the listing of
"vararg macros"[1,p2] as "changes to the existing macros for handling
variable-length argument lists" rather than "addition of support for
macros with variable argument lists". I should have checked further. I
didn't. Mea culpa.

Whilst this error was entirely attributable to my negligence (I am
{*filter*} myself vigorously with a cat-o-nine-tails as I type), and I
_do_ appreciate the correction (keeps me honest, makes me learn), I
would still point out that it was never suggested that support for
functions with variable argument lists was new, as the correction
(above) could be misconstrued if read out-of-context.

For the interested, on review, sections 6.10.3(4,5,10,12) [1,pp150-152]
and 6.10.3.1(2) [1,p152] deal directly with macros with variable
argument lists, as introduced to this thread by Larry's correction, and
there is a usage example in section 6.10.3.5(9) [1,p157].

I'll be more punctilious in future, but no prizes for spotting omissions
:)

Thanks again,

Emmet.

1: Joint Technical Committee ISO/IEC JTC1, subcommittee 22, "WG14/N869
   Committee Draft, January 18th, 1999". Available at:
   " http://www.*-*-*.com/ ;

2: Joint Technical Committee ISO/IEC JTC1, subcommittee 22, "New in
   C9X (in no particular order)".
   " http://www.*-*-*.com/ ;
--



Thu, 13 Feb 2003 03:00:00 GMT  
 Passing variable size arrays by value

Quote:

> What's on the list of major changes is *macros* with a variable number
> of arguments (which *is* new), not functions (which is not).

You are, of course, correct --- one can't get away with _anything_ in
here ;)

The addition, however, of VA_COPY 7.15.1.2 [1,p254] _is_ mentioned[1,p3]
in the list of major changes[1,p1-3] to the draft standard and in the
publically available web list[2] for the standard. This compounded my,
admittedly silly and careless, misunderstanding of the listing of
"vararg macros"[1,p2] as "changes to the existing macros for handling
variable-length argument lists" rather than "addition of support for
macros with variable argument lists". I should have checked further. I
didn't. Mea culpa.

Whilst this error was entirely attributable to my negligence (I am
{*filter*} myself vigorously with a cat-o-nine-tails as I type), and I
_do_ appreciate the correction (keeps me honest, makes me learn), I
would still point out that it was never suggested that support for
functions with variable argument lists was new, as the correction
(above) could be misconstrued if read out-of-context.

For the interested, on review, sections 6.10.3(4,5,10,12) [1,pp150-152]
and 6.10.3.1(2) [1,p152] deal directly with macros with variable
argument lists, as introduced to this thread by Larry's correction, and
there is a usage example in section 6.10.3.5(9) [1,p157].

I'll be more punctilious in future, but no prizes for spotting omissions
:)

Thanks again,

Emmet.

1: Joint Technical Committee ISO/IEC JTC1, subcommittee 22, "WG14/N869
   Committee Draft, January 18th, 1999". Available at:
   " http://www.*-*-*.com/ ;

2: Joint Technical Committee ISO/IEC JTC1, subcommittee 22, "New in
   C9X (in no particular order)".
   " http://www.*-*-*.com/ ;
--



Thu, 13 Feb 2003 03:00:00 GMT  
 Passing variable size arrays by value
the way printf() does it is by scanning the first (and absolutely necessary)
item it received for %'s, however many it counts, is then how many things it
pops off the stack.  Therefore, if you wanted to have similar functionality,
you would need to firstly have a required first item that somehow indicates
the number of further items there are going to be.  To, roughly, perform
this functionality in straight C you would just do something like this:

void myFuntion(unsigned int count, int* itemArray) {
    unsigned int L;
    for (L = 0; L < count; L++) {
        int myItem = itemArray[L];
        ...
    }
    return;

Quote:
}

otherwise you will need to do it in assembly where you can physically deal
with the pushes and pops, but I am unsure whether a C compiler will allow
you to prototype a function with the "..." attribute, or if that right was
reserved for the founders.  If you can then at least you won't have to do
all all the pushes in assembly (assuming your compiler allows inline
assembly--which is NOT supported in the ANSI/ISO standard.)

Assembly:

int addValues(unsigned int count);

int main(void) {
    int answer;
    int i = 1;
    int j = 2;
    int k = 3;
    int l = 4;
    unsigned int count = 4;
    _asm {
        push i;    /* officially you're supposed to push in revered order,
but for simple addition, */
        push j;    /* it doesn't matter */
        push k;
        push l;
        push count;
        call addValues;
        mov answer, eax;
    }
    printf("The total value was %d\n", answer);

    return 0;

Quote:
}

int addValues(unsigned int count) {
    _asm {
        pop ecx;        /* gets count */
        pop eax;        /* gets first value in our return register */
        dec ecx;        /* decrememnts count */
BACK:
        pop edx;        /* get next item */
        dec ecx;        /* decrement count */
        add eax, edx; /* add item to return register */
        cmp ecx, 0;    /* test if count has hit zero */
        jne BACK;    /* if not, loop back */
    }
    return;

Quote:
}

With variable length prototyping support:

int addValues(unsigned int count, ...);

int main(void) {
    int answer = addValues(4, 1, 2, 3, 4);
    printf("The total value was %d\n", answer);

    return 0;

Quote:
}

int addValues(unsigned int count) {
    _asm {
        pop ecx;        /* gets count */
       pop eax;        /* gets first value in our return register */
        dec ecx;        /* decrememnts count */
BACK:
        pop edx;        /* get next item */
        dec ecx;        /* decrement count */
        add eax, edx; /* add item to return register */
        cmp ecx, 0;    /* test if count has hit zero */
        jne BACK;    /* if not, loop back */
    }
    return;

Quote:
}

Now all you have to do is learn assembly!



Quote:
> Hi,

> I known that in C arrays when passed as function parameters are
> passed by reference (the pointer is really a reference to the
> array). To copy a entire array during the call I have to typedef
> it and pass the new type, is that ok? I was wondering how to
> pass a copy of the array during the call but for variable sized
> arrays (since in typedefs the size is fixed). Is it possible?

> Best regards,
> Rodrigo.

> --
> Rodrigo Augusto B. Ferreira
> Computer Science Graduate, UFMG/BRAZIL
> --


--



Thu, 13 Feb 2003 03:00:00 GMT  
 Passing variable size arrays by value

Quote:

> the way printf() does it is by scanning the first (and absolutely necessary)
> item it received for %'s, however many it counts, is then how many things it
> pops off the stack.  Therefore, if you wanted to have similar functionality,
> you would need to firstly have a required first item that somehow indicates
> the number of further items there are going to be.

No, so long as you don't try to use nonexistent arguments
there is no need to count them.  Another common approach
(e.g. execl() in POSIX) is to use a special value for an
argument as an indication that that is the last argument.

Quote:
> otherwise you will need to do it in assembly where you can physically deal
> with the pushes and pops, but I am unsure whether a C compiler will allow
> you to prototype a function with the "..." attribute, or if that right was
> reserved for the founders.  If you can then at least you won't have to do
> all all the pushes in assembly (assuming your compiler allows inline
> assembly--which is NOT supported in the ANSI/ISO standard.)

??  Of course the programmer can use variable-argument
functions, and there are macros in <stdarg.h> for handling
them.  There is no need for assembly language for this.
--



Fri, 14 Feb 2003 03:00:00 GMT  
 
 [ 19 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Passing variable size arrays of structs with COM using size_is

2. passing variable values

3. Passing variable-size data between trampolines

4. Help - I need to set variable A = value held in variable named in variable B

5. Passing an array by value?

6. Passing array by value

7. passing an array of structs - Is it by value or reference

8. BUG in C++: array size passed to a C# code

9. Passing 2-D arrays of non-constant size

10. 3D array of varying size passed to a function

11. Passing a bidimensional array of unknown size

12. calculating the size of an array passed to a function

 

 
Powered by phpBB® Forum Software