Array arguments

  • Thread starter =?ISO-8859-1?Q?Ney_Andr=E9_de_Mello_Zunino?=
  • Start date
?

=?ISO-8859-1?Q?Ney_Andr=E9_de_Mello_Zunino?=

Hello.

I have a question regarding arrays when used as arguments in function
calls. In a situation like the following:

void foo(int array[2])
{
// ...
}

int bar[2] = {2, 3};
foo(bar);

What happens to the 'bar' "object" being passed to the function? I
expected it to be passed as it is, i.e., an "object" of type int [2],
without any conversion taking place. However, section 7.2.1 of
Stroustrup's TCPL 3rd Edition reads:

"If an array is used as a function argument, a pointer to its initial
element is passed."

and a bit further:

"...arrays differ from other types in that an array is not (and cannot
be) passed by value."

Does it mean that, in the sample code above, 'bar' is actually being
passed as 'int*' and then converted back to int [2] in the called
function? I am aware that the name of arrays may be used as pointers to
its first elements and that this conversion takes place automatically,
but I thought that might be different when explicitly declaring an
argument as having a type such as int [2].

Why can't arrays be passed by value? I find it somewhat inconsistent
once one could easily imply reference semantics by using pointer or
reference syntax:

void foo(int (*array)[2]) {}
void foo(int (&array)[2]) {}

I would appreciate if these issues could be elaborated a little so that
I can clear up my concepts.

Thank you,
 
J

johnny

Ney said:
Why can't arrays be passed by value? I find it somewhat inconsistent
once one could easily imply reference semantics by using pointer or
reference syntax:

Besides being the standard, it takes less time to pass arrays by reference
than by value. Imagine trying to pass an array of several thousand elements
(or even 100) of type double or type string. To pass all those array values
would take a significant amount of time. IMO, it seems like a better idea
to pass the address of the first element and then index into the array to
retrieve the value of each element.
 
J

Jack Klein

Hello.

I have a question regarding arrays when used as arguments in function
calls. In a situation like the following:

void foo(int array[2])
{
// ...
}

int bar[2] = {2, 3};
foo(bar);

What happens to the 'bar' "object" being passed to the function? I
expected it to be passed as it is, i.e., an "object" of type int [2],
without any conversion taking place. However, section 7.2.1 of
Stroustrup's TCPL 3rd Edition reads:

"If an array is used as a function argument, a pointer to its initial
element is passed."

and a bit further:

"...arrays differ from other types in that an array is not (and cannot
be) passed by value."

Does it mean that, in the sample code above, 'bar' is actually being
passed as 'int*' and then converted back to int [2] in the called
function? I am aware that the name of arrays may be used as pointers to
its first elements and that this conversion takes place automatically,
but I thought that might be different when explicitly declaring an
argument as having a type such as int [2].

Use of the name 'bar' in almost all contexts results in a conversion
to a pointer to the first element of the array. Exceptions are when
applying the & and sizeof operators to the name of an array.

But inside the function, it is NOT converted back to int[2], it is
received as, is handled as, and remains a pointer to int. You may be
confused by the fact that C++ allows array subscripting notation to be
used on pointers.

For fundamental types and even user defined types where operator [] is
not overloaded, C++ inherits pointer behavior from C. Array access
such as 'bar[1]' is actually defined in pointer terms. The expression
is processed by the compiler as though it were written *(bar + 1).
Why can't arrays be passed by value? I find it somewhat inconsistent

Arrays can be passed by value. Merely place an array inside a class
or struct and pass that object by value.
once one could easily imply reference semantics by using pointer or
reference syntax:

void foo(int (*array)[2]) {}

Yes, this is a pointer to an array of two ints. It has the same
address as the array, but a different type.
void foo(int (&array)[2]) {}

Likewise, this is a reference to an array of two ints.
I would appreciate if these issues could be elaborated a little so that
I can clear up my concepts.

Thank you,

This is the way that C was originally defined, more than three decades
ago, for reasons that made sense to its designers in the context for
which it was designed at the time. For backwards compatibility with
millions of likes of existing C and C++ code, this will never change.

C++ offers alternatives to arrays, such as vectors, which can do what
you want. Or if you have a fixed-size array you can do what I
mentioned above, make it a member of a struct or class and then you
can both pass and return it by value.
 
?

=?ISO-8859-1?Q?Ney_Andr=E9_de_Mello_Zunino?=

Jack Klein wrote:

[...]
But inside the function, it is NOT converted back to int[2], it is
received as, is handled as, and remains a pointer to int. You may be
confused by the fact that C++ allows array subscripting notation to be
used on pointers.

Thank you, Jack, for the clarifications. But, if the array argument is
received and handled as a pointer to its element type, regardless of the
way it (the argument) is declared, what are the differences/implications
of using

void foo(int array[2])

as opposed to

void foo(int* array)

?

[...]
This is the way that C was originally defined, more than three decades
ago, for reasons that made sense to its designers in the context for
which it was designed at the time. For backwards compatibility with
millions of likes of existing C and C++ code, this will never change.

C++ offers alternatives to arrays, such as vectors, which can do what
you want. Or if you have a fixed-size array you can do what I
mentioned above, make it a member of a struct or class and then you
can both pass and return it by value.

I use vectors everywhere I can, keeping the use of bare arrays to a
minimum. I was actually just experimenting with the syntax in order to
clear up some concepts. I think you have made it quite clear that the
rules involved are derived from C++'s intended commitment to having
backwards compatibility with C.

Thank you again,
 
J

John Harrison

Ney André de Mello Zunino said:
Jack Klein wrote:

[...]
But inside the function, it is NOT converted back to int[2], it is
received as, is handled as, and remains a pointer to int. You may be
confused by the fact that C++ allows array subscripting notation to be
used on pointers.

Thank you, Jack, for the clarifications. But, if the array argument is
received and handled as a pointer to its element type, regardless of the
way it (the argument) is declared, what are the differences/implications
of using

void foo(int array[2])

as opposed to

void foo(int* array)

There is no difference.

john
 

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

No members online now.

Forum statistics

Threads
474,175
Messages
2,570,942
Members
47,489
Latest member
BrigidaD91

Latest Threads

Top