Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Difference between array and pointer - arguments

71 views
Skip to first unread message

JiiPee

unread,
Apr 28, 2016, 7:52:07 AM4/28/16
to
What is the difference between arguments:

void foo(char a[]) {}

and

void foo(char* a) {}

Can the foo use the array the same way in both?

char k[] = "hello";

creates memory for k-array and copies hello there. But I can see char
a[] does not make a new array and copy the calling values there... it
seems like its a pointer only. Is this correct? Is I call foo("John") ,
i can see that I cannot modify a's values, so its clearly a pointer to
John-literal. Are both of those just pointer arguments?

Michael Tsang

unread,
Apr 28, 2016, 8:26:35 AM4/28/16
to
They are the same (pass by pointer) as defined by the specification
--
Sent from KMail

JiiPee

unread,
Apr 28, 2016, 8:28:17 AM4/28/16
to
On 28/04/2016 13:26, Michael Tsang wrote:
> They are the same (pass by pointer) as defined by the specification

oh ok thanks


Victor Bazarov

unread,
Apr 28, 2016, 9:24:28 AM4/28/16
to
Built-in arrays are not first-class objects in C++ (and never have
been). You can't pass them by value (as you seem to expect from the
former declaration). You can pass them by reference, but you need to
know the exact size of the array. What book are you reading that
doesn't explain that?

V
--
I do not respond to top-posted replies, please don't ask

Alf P. Steinbach

unread,
Apr 28, 2016, 9:38:01 AM4/28/16
to
On 28.04.2016 13:51, JiiPee wrote:
> What is the difference between arguments:
>
> void foo(char a[]) {}
>
> and
>
> void foo(char* a) {}
>
> Can the foo use the array the same way in both?

They are the same because for a formal argument type, array decays to
pointer.

There is a similar decay for a function type as formal argument type, it
also decays to pointer.

For functions you can use a function reference as formal argument type,
in order to express the intent that your function is not called with a
nullpointer as actual argument.

For raw arrays this is AFAIK not possible for unknown array size,
because a reference to array of unknown bounds is just invalid.

In other contexts than formal argument type the type itself doesn't
change, but an expression of one of these types has implicit conversion
to pointer when the context requires a pointer.


> char k[] = "hello";

Is very different because it's not a formal argument type.

This results in k getting the type `char[6]`.


Cheers & hth.,

- Alf

Barry Schwarz

unread,
Apr 28, 2016, 2:23:30 PM4/28/16
to
Despite the lexical similarity, there is a significant difference
between the definition of an object (such as k) and the definition of
a parameter (such as a). Functions receive the value of the arguments
specified by the calling statement in the corresponding parameters
specified by the function definition ***as if by assignment***.

With a few exceptions that don't apply here, an unsubscripted array
name in an expression is automatically converted to a pointer to the
first element of the array with type pointer to element type. This is
what allows
char *x = k;
to work and x points to the 'h'. Similarly, when you execute
foo(k);
it is identical to
foo(&k[0]);
regardless of which signature you use for foo.

Note that sizeof k will evaluate to 6 while sizeof a will evaluate to
4 (or 8) regardless of the size of the array in the calling statement.
If foo needs to now how big the array is, the calling function must
provide that datum somehow.

For one dimensional arrays, this is pretty straight forward. It gets
a bit more complex for multi-dimensional arrays but we can save that
for a later discussion.

--
Remove del for email

Chris Vine

unread,
Apr 28, 2016, 3:36:20 PM4/28/16
to
On Thu, 28 Apr 2016 12:51:55 +0100
As has been mentioned by others, by virtue of pointer decay the two are
the same.

Possibly you have in the back of your mind the passing of arrays by
reference, which is a little used but quite useful idiom because it
retains the type information and enforces the size of the array, and
therefore can help prevent buffer overruns in some cases. With this
signature:

void foo(char (&a)[4]) {}

'a' retains its quality as a reference to an array of char of size 4,
and it will refuse to compile if passed a char array of any other size.

Chris

JiiPee

unread,
Apr 28, 2016, 3:37:49 PM4/28/16
to
On 28/04/2016 14:37, Alf P. Steinbach wrote:
> On 28.04.2016 13:51, JiiPee wrote:
>> What is the difference between arguments:
>>
>> void foo(char a[]) {}
>>
>> and
>>
>> void foo(char* a) {}
>>
>> Can the foo use the array the same way in both?
>
> They are the same because for a formal argument type, array decays to
> pointer.

ok, so this explains it, this is what I wanted to know

>
>
>> char k[] = "hello";
>
> Is very different because it's not a formal argument type.
>
> This results in k getting the type `char[6]`.
>

sure, so argument is different in this

With integer they are not different:

int a =3;

void foo(int a)

foo(3)

also is going to do a copy: a =3. The same with objects... so array is
different here it does not allocate memory.

JiiPee

unread,
Apr 28, 2016, 3:41:08 PM4/28/16
to
On 28/04/2016 19:23, Barry Schwarz wrote:
> On Thu, 28 Apr 2016 12:51:55 +0100, JiiPee <n...@notvalid.com> wrote:
>
>> What is the difference between arguments:
>>
>> void foo(char a[]) {}
>>
>> and
>>
>> void foo(char* a) {}
>>
>> Can the foo use the array the same way in both?
>>
>> char k[] = "hello";
>>
>> creates memory for k-array and copies hello there. But I can see char
>> a[] does not make a new array and copy the calling values there... it
>> seems like its a pointer only. Is this correct? Is I call foo("John") ,
>> i can see that I cannot modify a's values, so its clearly a pointer to
>> John-literal. Are both of those just pointer arguments?
> Despite the lexical similarity, there is a significant difference
> between the definition of an object (such as k) and the definition of
> a parameter (such as a). Functions receive the value of the arguments
> specified by the calling statement in the corresponding parameters
> specified by the function definition ***as if by assignment***.
>
> With a few exceptions that don't apply here, an unsubscripted array
> name in an expression is automatically converted to a pointer to the
> first element of the array with type pointer to element type.

ok, this exception I was wondering... becouse normally you make a copy
of the calling argument

Paavo Helde

unread,
Apr 28, 2016, 4:52:06 PM4/28/16
to
In C++, yes. But raw arrays are a C feature, developed almost 50 years
ago. Note that the original C did not have mandatory function
prototypes, so when an array is passed to a function it had to be
compiled always the same, regardless of the actual function definition.
And this default array pass was chosen to consist of decaying to the
pointer to the first element. I guess this was done both for performance
and flexibility. C was a very pragmatic language.

Note that in C one can also pass arrays by copy, but this requires
embedding them in a struct which is more cumbersome.

The default makes sense because copy of the array is rarely needed.
That's why most std::vector parameters in C++ are passed as (const or
non-const) references, avoiding the default 'copy' behavior.


Barry Schwarz

unread,
Apr 28, 2016, 5:17:52 PM4/28/16
to
Did you not read the rest of the message?

What part of "as if by assignment" was unclear? While for some object
types assignment may be equivalent to copy, for others it is
definitely not. Do you think
char* p = k;
does any kind of copy from the array?

JiiPee

unread,
Apr 28, 2016, 7:53:06 PM4/28/16
to
no, but:

char aa[] = "Hello";

*does* copy the hello into it. thats what I mean.... that array is not
"consistant" : sometimes it means copy sometimes it means pointer copy.
But I understand that now....its ok.

>

JiiPee

unread,
Apr 28, 2016, 7:56:03 PM4/28/16
to
On 28/04/2016 20:35, Chris Vine wrote:
> void foo(char (&a)[4]) {}
>
> 'a' retains its quality as a reference to an array of char of size 4,
> and it will refuse to compile if passed a char array of any other size.

interesting.. good to know

Barry Schwarz

unread,
Apr 29, 2016, 12:44:33 AM4/29/16
to
Your declaration above is not an assignment, despite what it looks
like. It is initialization.

And the same "inconsistency" applies to initialization. Your
declaration will copy data while
char *bb = "Hello";
will not.

Öö Tiib

unread,
Apr 29, 2016, 1:33:53 AM4/29/16
to
Note that you yourself started that confusion above by implying that
your 'char* p = k;' involves assignment.

>
> And the same "inconsistency" applies to initialization. Your
> declaration will copy data while
> char *bb = "Hello";
> will not.

ISO C++ forbids converting a string constant to 'char*'.

Juha Nieminen

unread,
Apr 30, 2016, 5:40:17 AM4/30/16
to
Chris Vine <chris@cvine--nospam--.freeserve.co.uk> wrote:
> Possibly you have in the back of your mind the passing of arrays by
> reference, which is a little used but quite useful idiom because it
> retains the type information and enforces the size of the array, and
> therefore can help prevent buffer overruns in some cases. With this
> signature:
>
> void foo(char (&a)[4]) {}
>
> 'a' retains its quality as a reference to an array of char of size 4,
> and it will refuse to compile if passed a char array of any other size.

It is actually a very useful feature. It's how eg. std::end() and
range-based for loops for static arrays work. They are sometimes
useful for all kinds of things in templated code.

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

Cholo Lennon

unread,
May 2, 2016, 10:37:45 AM5/2/16
to
A more generic version could be:

template<std::size_t N>
void foo(char (&a)[N]) { ... }


To avoid code duplication due to multiple instantiations of foo (for
every array size) you could forward foo to an internal function:

void internal_foo(char* a, std::size_t size);

template<std::size_t N>
void foo(char (&a)[N])
{
internal_foo(a, N);
}


Regards


--
Cholo Lennon
Bs.As.
ARG

Cholo Lennon

unread,
May 2, 2016, 11:27:47 AM5/2/16
to
On 05/02/2016 12:02 PM, Stefan Ram wrote:
> Cholo Lennon <cholo...@hotmail.com> writes:
>> A more generic version could be:
>> template<std::size_t N>
>> void foo(char (&a)[N]) { ... }
>
> Yeah, Herb Sutter on 2015-09-22 said/wrote (CppCon day 2):
>
> »Don't use array-to-pointer decay.«.
>

The quoted templated foo is not using array to pointer decay, it's just
using a reference to an array.

Array to pointer decay is, of course, used by the solution to avoid code
duplication (foo + internal_foo) in the 2nd part of my post


> And
>
> »use array_view«.

Zaphod Beeblebrox

unread,
May 2, 2016, 1:14:41 PM5/2/16
to
On Thursday, 28 April 2016 12:52:07 UTC+1, JiiPee wrote:

> What is the difference between arguments:
>
> void foo(char a[]) {}
>
> and
>
> void foo(char* a) {}

It's exactly the same.

> Can the foo use the array the same way in both?
>
> char k[] = "hello";

Yes, but it needs to know the number of items, so either you use a "sentinel" value at the end of the array (typically '\0' for strings) or you pass in the number of items in the array.

> creates memory for k-array and copies hello there.

This is one of the 3 cases when the name of an array *decays* to the pointer to its first element. The other cases are the use of sizeof and the & address-of operator. When you pass the name of an array to a function, instead, it decays to a pointer to its first element.

> a[] does not make a new array and copy the calling values there... it
> seems like its a pointer only. Is this correct?

'a' is a always a pointer, in your case.


Zaphod Beeblebrox

unread,
May 2, 2016, 1:16:54 PM5/2/16
to
On Friday, 29 April 2016 00:53:06 UTC+1, JiiPee wrote:

[...]
> *does* copy the hello into it. thats what I mean.... that array is not
> "consistant" : sometimes it means copy sometimes it means pointer copy.
> But I understand that now....its ok.

Yes, because the initialization via literal, the use of sizeof and the use of & are the only three cases when the name of an array does not decay to the pointer to its first element.
0 new messages