Difference between char [ ] and char * as formal parameters

B

bintom

Is there any difference between the following function prototypes?

void func(int arr [ ]);

and

void func(int *ptr);

When I print the address of arr and ptr, they reflect the same value
(address of the array). I can even say arr++ and ptr++ without any
problem.

So, is there any difference between the two?

Bintom
 
A

Alf P. Steinbach /Usenet

* bintom, on 27.06.2010 19:11:
Is there any difference between the following function prototypes?

void func(int arr [ ]);

and

void func(int *ptr);

When I print the address of arr and ptr, they reflect the same value
(address of the array). I can even say arr++ and ptr++ without any
problem.

So, is there any difference between the two?

As a formal argument's top level type an array decays to pointer, a function
decays to pointer, and wrt. the function type (e.g. what you can overload) top
level const's are removed.

A textbook will explain this.

If you cannot afford a textbook then a draft of the standard might be your best
bet for a resource. Drafts are free. The standard is, however, hideously complex.


Cheers & hth.,

- Alf
 
Ö

Öö Tiib

Is there any difference between the following function prototypes?

void func(int arr [ ]);

        and

void func(int *ptr);

When I print the address of arr and ptr, they reflect the same value
(address of the array). I can even say arr++ and ptr++ without any
problem.

So, is there any difference between the two?

They have same functions signature. Also all compilers will diagnose
them as same:

void func( int arr[] ) {}
void func( int* ptr ) {} // error: func already defined

The difference is that arr is constant within function body. So you
can type for example ptr++ but can not arr++. People usually use first
notation to indicate that there is expected array and second notation
to indicate that it is expected to point at single object (or null
pointer).
 
B

bintom

Can't agree with you Oo Tiib, I ran the following code and there was
absolutely no problem with arr++;



void func1(int arr[])
{ arr++;
cout << *arr;
}

void func2(int *iptr)
{ iptr++;
cout << *iptr;
}

int main()
{ int arr[21];

func1(arr);
cout << "\n\n";
func2(arr);

return 0;
}
 
B

bintom

I have a number of text books, from Prata's C++ Primer to Robert
Lafore's book on C++. But I haven't seen this topic tackled head-on!
 
P

Paul Bibbings

bintom said:
Is there any difference between the following function prototypes?

void func(int arr [ ]);

and

void func(int *ptr);

When I print the address of arr and ptr, they reflect the same value
(address of the array). I can even say arr++ and ptr++ without any
problem.

So, is there any difference between the two?

It's amazing how, after some passage of time and experience, it is
sometimes necessary to have to think anew about the more basic stuff
learnt a long time ago. I'd initially merely wanted to say no
difference, but then had to think about it from various angle and test a
few things. The key here is the array-to-pointer conversion.

19:08:23 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/CLCPP $cat array_ptr_comp.cpp
// file: array_ptr_comp.cpp

#include <iostream>

void f(int arr[])
{
std::cout << "\nsizeof(arr): " << sizeof(arr) << '\n';
std::cout << "&arr : " << arr << '\n';
std::cout << "*arr++ : " << *arr++ << '\n';
std::cout << "*arr : " << *arr << '\n';
}


void g(int *ptr)
{
std::cout << "\nsizeof(ptr): " << sizeof(ptr) << '\n';
std::cout << "&ptr : " << ptr << '\n';
std::cout << "*ptr++ : " << *ptr++ << '\n';
std::cout << "*ptr : " << *ptr << '\n';
}

int main()
{
int i_arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
void (*f_ptr)(int []) = 0;
void (*g_ptr)(int *) = 0;
f_ptr = &g;
g_ptr = &f;
f_ptr(i_arr);
g_ptr(i_arr);
}

You can see that the array-to-pointer conversion is applied even when
generating the function signature (compiled with gcc-4.4.3):

/cygdrive/d/CPPProjects/CLCPP $nm --demangle --defined-only
array_ptr_comp.o
// ...
00000000 T f(int*)
000000e2 T g(int*)

Regards

Paul Bibbings
 
Ö

Öö Tiib

Can't agree with you Oo Tiib, I ran the following code and there was
absolutely no problem with arr++;

Yes, i stand corrected. Appears that the diagnostic was from other
tool in my toolset. Then there are absolutely no difference for
compiler.
 
P

Paul Bibbings

Öö Tiib said:
Is there any difference between the following function prototypes?

void func(int arr [ ]);

        and

void func(int *ptr);

When I print the address of arr and ptr, they reflect the same value
(address of the array). I can even say arr++ and ptr++ without any
problem.

So, is there any difference between the two?

They have same functions signature. Also all compilers will diagnose
them as same:

void func( int arr[] ) {}
void func( int* ptr ) {} // error: func already defined

The difference is that arr is constant within function body. So you
can type for example ptr++ but can not arr++.

I don't think that this is the case. Having the same signature - void
func(int *) - they have the same semantics, surely.

Comeau is certainly okay with:

void f(int arr[])
{
arr++;
}

int main()
{
int i_arr[] = { 1, 2, 3 };
f(i_arr);
}

as is gcc.

Regards

Paul Bibbings
 
Ö

Öö Tiib

Tiib said:
Is there any difference between the following function prototypes?
void func(int arr [ ]);
and
void func(int *ptr);
When I print the address of arr and ptr, they reflect the same value
(address of the array). I can even say arr++ and ptr++ without any
problem.
So, is there any difference between the two?
They have same functions signature. Also all compilers will diagnose
them as same:
 void func( int arr[] ) {}
 void func( int* ptr ) {}  // error: func already defined
The difference is that arr is constant within function body. So you
can type for example ptr++ but can not arr++.

I don't think that this is the case.  Having the same signature - void
func(int *) - they have the same semantics, surely.

Comeau is certainly okay with:

   void f(int arr[])
   {
      arr++;
   }

   int main()
   {
      int i_arr[] = { 1, 2, 3 };
      f(i_arr);
   }

as is gcc.

Yes, i mixed it up with other static checking tool that tries to make
difference between pointers used as arrays, pointers used as iterators
and pointers used as pointers to objects. Pointers are so multi-
purpose that it is awfully error-prone.
 
A

Alf P. Steinbach /Usenet

* bintom, on 27.06.2010 20:23:
I have a number of text books, from Prata's C++ Primer to Robert
Lafore's book on C++. But I haven't seen this topic tackled head-on!

Oh well.

What you may need to know is that in C++ you can pass an array by reference, as
an array. Due to the reference it's then no longer the formal arg's top level
type, hence no decay to pointer type. The syntax is, well, perhaps perplexing:

void foo( char (&arr)[6] );

Hm, or was it the other way round, "arr&"?

Check it.

Anyway, then you can call foo with "hello" as argument, but "hi" should fail.

The only practical use that I'm aware of is obtaining an array's size:

template< typename Elem, ptrdiff_t N )
ptrdiff_t size( Elem (&)[N] ) { return N; }

For this usage no name is required, so I don't go around remembering the
placement of the name. :)


Cheers,

- Alf
 
P

Paul Bibbings

Alf P. Steinbach /Usenet said:
* bintom, on 27.06.2010 20:23:
I have a number of text books, from Prata's C++ Primer to Robert
Lafore's book on C++. But I haven't seen this topic tackled head-on!

Oh well.

What you may need to know is that in C++ you can pass an array by
reference, as an array. Due to the reference it's then no longer the
formal arg's top level type, hence no decay to pointer type. The
syntax is, well, perhaps perplexing:

void foo( char (&arr)[6] );

Hm, or was it the other way round, "arr&"?

Check it.

Right first time.
Anyway, then you can call foo with "hello" as argument, but "hi" should fail.

The only practical use that I'm aware of is obtaining an array's size:

template< typename Elem, ptrdiff_t N )
ptrdiff_t size( Elem (&)[N] ) { return N; }

For this usage no name is required, so I don't go around remembering
the placement of the name. :)

This usage always strikes me as, a what? ... an oddity, a /cheat/, a
something. One of the frustrations, perhaps, of the beginner is that
the array-to-pointer conversion and all the rules surrounding that means
that the size of an array is lost when passing an array to a function
defined as either void f(int *), void f(int []) or even:

void f(int arr[10])
{ /* Top level array bound ignored. Size of array not available */ }

int main()
{
int i_arr[3] = { 1, 2, 3 };
f(i_arr); // OK
}

Even:

void f(int (&arr)[10])
{ /* Top-level array bound significant. Size of array still not
available */ }

int main()
{
int i_arr[3] = { 1, 2, 3 };
f(i_arr); // error: invalid initialization of reference of
// type int(&)[10] from expression of type int[3]
int i_arr2[10];
f(i_arr2); // OK
}


So that you, conventionally, need something like:

void f(int arr[], size_t sz)
{
for (size_t i = 0; i < sz; ++i)
// ...
}

int main()
{
int i_arr[10];
f(i_arr, 10);
}

But then, all of a sudden, it feels like a cheat to be able to use a
function template and `deduce' the size:

template<typename T, size_t N>
void f(T (&arr)[N])
{
for (size_t i = 0; i < N; ++i)
;
}

int main()
{
int i_arr[10];
f(i_arr);
}

Your example above illustrates just how useful this ability to deduce
the size of an array bound can be.

Regards

Paul Bibbings
 

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
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top