Reference to an Array of some dimension

A

arnuld

this programme gives unusual output. i am not able to find out where the
semantic bug lies:


/* C++ Primer - 4/e
*
* an example from section section 7.2.4, page 241 * STATEMENT
* write a function that prints the elements of an array. don't use
pointer to an array as parameter because pointer will be copied, use
reference to the array instead.
*
*/


#include <iostream>


/* prints the elements of an array. i could have used subscripting but the
point here is the understanding of pointers and references */
void print_array( int (&arr)[3], const size_t arr_size ) {
int* pbegin = arr;
int* pend = pbegin + arr_size;

while( pbegin != pend)
{
std::cout << *pbegin++ << std::endl;
}

}


int main()

{
const size_t arr_size = 3;
int arr_3[3] = {10, 20, 30};

print_array( (&arr_3)[3], arr_size);

return 0;
}

/* OUTPUT
~/programming/cpp $ g++ -ansi -pedantic -Wall -Wextra test.cpp
~/programming/cpp $ ./a.out
-1079705144
-1210589296
1
~/programming/cpp $

*/
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

this programme gives unusual output. i am not able to find out where the
semantic bug lies:


/* C++ Primer - 4/e
*
* an example from section section 7.2.4, page 241 * STATEMENT
* write a function that prints the elements of an array. don't use
pointer to an array as parameter because pointer will be copied, use
reference to the array instead.
*
*/


#include <iostream>


/* prints the elements of an array. i could have used subscripting but the
point here is the understanding of pointers and references */

I'm not so sure about that, since you are passing an array, not a
pointer to the first element, you know the number of elements in the
array, so a for-loop would be perfect.
void print_array( int (&arr)[3], const size_t arr_size ) {

You know that there there are 3 elements and the function is hard-coded
for such arrays, no need for the second argument.
int* pbegin = arr;
int* pend = pbegin + arr_size;

while( pbegin != pend)
{
std::cout << *pbegin++ << std::endl;
}

Could be replaced with

for (size_t i = 0; i < 3; ++i)
{
std::cout << arr << std::endl;
}
}


int main()

{
const size_t arr_size = 3;

Drop this, or use it to set the size of the array.
int arr_3[3] = {10, 20, 30};

print_array( (&arr_3)[3], arr_size);

I'm not really sure, but I think this passes the address of the fourth
element, not the array. When passing an array by reference you do it
just like any other variable you pass by reference, with its name:

print_array(arr_3);
 
A

arnuld

I'm not so sure about that, since you are passing an array, not a
pointer to the first element, you know the number of elements in the
array, so a for-loop would be perfect.

i know but it produces error:

for( int* pbegin = arr, pend = pbegin + arr_size;
pbegin != pend; ++pbegin)
{
std::cout << *pbegin++ << std::endl;
}


7.2.4_print-array.cpp: In function 'void print_array(int (&)[3],
size_t)': 7.2.4_print-array.cpp:23: error: invalid conversion from
'int*' to 'int'

7.2.4_print-array.cpp:23: error: ISO C++ forbids comparison between
pointer and integer

i did not understand why it was taking "pend" as integer. and page 117 of
C++ Primer says: i am stupid because i wrote that: "int* pbegin, pend"
thing and expected both of them to be a pointer, in fact they are 2
different types"

void print_array( int (&arr)[3], const size_t arr_size ) {

You know that there there are 3 elements and the function is hard-coded
for such arrays, no need for the second argument.

actually, i wanted it to be like this: "int (&arr)[]" but that is
compile time error :(

7.2.4_print-array.cpp:18: error: parameter 'arr' includes reference
to array of unknown bound 'int []'

for (size_t i = 0; i < 3; ++i)
{
std::cout << arr << std::endl;
}


yes, it is easy and the author wants me to use pointers, arrays and
references.

print_array( (&arr_3)[3], arr_size);
I'm not really sure, but I think this passes the address of the fourth
element, not the array. When passing an array by reference you do it
just like any other variable you pass by reference, with its name:

print_array(arr_3);

and i was passing, print_array(&arr_3[]), heck....references always
confuse me.


BTW, here is the new code, compiles and runs fine and th eonly thing i
wanted to implement was passing a reference to an array of unknown array
(Aye.. do i need Dynamic Array for this ?)

/* C++ Primer - 4/e
*
* an example from section section 7.2.4, page 241
* STATEMENT
* write a function that prints the elements of an array. don't use
pointer to an array as parameter because pointer will be copied, use
reference to the array as parameter.
*
*/


#include <iostream>


/* prints the elements of an array. i could have used subscripting but the
point here is the understanding of pointers and references */
void print_array( int (&arr)[3], const size_t arr_size ) {
for( int *pbegin = arr, *pend = pbegin + arr_size; pbegin != pend;
++pbegin)
{
std::cout << *pbegin << std::endl;
}

}


int main()

{
const size_t arr_size = 3;
int arr_3[arr_size] = {10, 20, 30};

print_array( arr_3, arr_size);

return 0;
}

/* OUTPUT
~/programming/cpp $ g++ -ansi -pedantic -Wall -Wextra
7.2.4_print-array.cpp ~/programming/cpp $ ./a.out
10
20
30
~/programming/cpp $

*/
 
R

Robert Bauck Hamar

arnuld said:
I'm not so sure about that, since you are passing an array, not a
pointer to the first element, you know the number of elements in the
array, so a for-loop would be perfect.

i know but it produces error:

for( int* pbegin = arr, pend = pbegin + arr_size;
pbegin != pend; ++pbegin)
{
std::cout << *pbegin++ << std::endl;
}


7.2.4_print-array.cpp: In function 'void print_array(int (&)[3],
size_t)': 7.2.4_print-array.cpp:23: error: invalid conversion from
'int*' to 'int'

7.2.4_print-array.cpp:23: error: ISO C++ forbids comparison between
pointer and integer

i did not understand why it was taking "pend" as integer. and page 117 of
C++ Primer says: i am stupid because i wrote that: "int* pbegin, pend"
thing and expected both of them to be a pointer, in fact they are 2
different types"

Seems to me that you are unaware of how variable declarations work in C++.
int* a,b;
declares a as a pointer to int, and b as a pointer. This is because
declarations are split in two syntax elements: The type and the declarator
list. Here, the type is int, and the declarator list is *a and b, and the
declarations says: "*a" and "b" should be recognised as ints. That's why it
is common to write
int *a, b
instead. It demonstrates to the reader that the asterisk belongs to a only.
Of course, the clearer and advisable solution is to write two declarations.

In your for loop, write:
for (int* iter = arr; iter < arr + arr_size; ++iter) {
std::cout << *iter << std::endl; //not *iter++.
}

I chose another name than pbegin for the iterator, it does only once point
to the beginning of the array. The compiler should be smart enough to
compute arr + arr_size only once, you don't need to cache this value
yourself.
void print_array( int (&arr)[3], const size_t arr_size ) {

You know that there there are 3 elements and the function is hard-coded
for such arrays, no need for the second argument.

actually, i wanted it to be like this: "int (&arr)[]" but that is
compile time error :(

Yes, it's a compile time error. C++ has to know how large the array is to
reference it.
BTW, here is the new code, compiles and runs fine and th eonly thing i
wanted to implement was passing a reference to an array of unknown array

Cannot be done. But you could use templates to let the compiler do the work
of figuring out the array sizes.
/* C++ Primer - 4/e
*
* an example from section section 7.2.4, page 241
* STATEMENT
* write a function that prints the elements of an array. don't use
pointer to an array as parameter because pointer will be copied, use
reference to the array as parameter.
*
*/


#include <iostream>


/* prints the elements of an array. i could have used subscripting but the
point here is the understanding of pointers and references */
void print_array( int (&arr)[3], const size_t arr_size ) {
for( int *pbegin = arr, *pend = pbegin + arr_size; pbegin != pend;
++pbegin)
{
std::cout << *pbegin << std::endl;
}

}

#include <cstddef> // for std::size_t

/* template solution */
template <std::size_t arr_size>
void print_array(int (&arr)[arr_size]) {
// ...
}

call it with

print_array(arr_3);
int main()

{
const size_t arr_size = 3;
int arr_3[arr_size] = {10, 20, 30};

print_array( arr_3, arr_size);

return 0;
}

/* OUTPUT
~/programming/cpp $ g++ -ansi -pedantic -Wall -Wextra
7.2.4_print-array.cpp ~/programming/cpp $ ./a.out
10
20
30
~/programming/cpp $

*/
 
F

Frank Birbacher

Hi!
i did not understand why it was taking "pend" as integer. and page 117 of
C++ Primer says: i am stupid because i wrote that: "int* pbegin, pend"
thing and expected both of them to be a pointer, in fact they are 2
different types"

Yes, two types: pinter and int. The "*" does not count for the second
variable.
actually, i wanted it to be like this: "int (&arr)[]" but that is
compile time error :(

Yes, there is no reference to an array of unknown size. That just
doesn't exist. That's why everywhere you see "int* array, int size" as
arguments ("int" as size, although it should be "size_t", but they
aren't using const neither).

"The C++ way" of doing it is to use "iterators". In this case they would
just be pointers to int:

void print_int_array(int const* const pbegin, int const* const pend)
{
while(pbegin != pend)
cout << *pbegin++ << '\n';
}

This can be made to work with other thing that aren't an array. You need
templates for that. I guess you are not that far yet in your book, so
I'll skip the example.

Frank
 
J

James Kanze

arnuld said:
actually, i wanted it to be like this: "int (&arr)[]" but that is
compile time error :(
Yes, there is no reference to an array of unknown size.

That's what g++ says, but I can't find the restriction in the
standard. Where does the standard says that something like:

extern int arr[] ;

void
f( int (&a)[] )
{
}

void
g()
{
f( arr ) ;
}

Is forbidden?

What is true is that unlike incomplete class types, an array of
unknown size is considered a distinct type. So you can't pass
an array of known size to f, above. (Which in turn makes
parameters like that of f, above, a bit useless.)
 
J

James Kanze

this programme gives unusual output. i am not able to find out where the
semantic bug lies:
/* C++ Primer - 4/e
*
* an example from section section 7.2.4, page 241 * STATEMENT
* write a function that prints the elements of an array. don't use
pointer to an array as parameter because pointer will be copied, use
reference to the array instead.
*
*/
#include <iostream>
/* prints the elements of an array. i could have used subscripting but the
point here is the understanding of pointers and references */
void print_array( int (&arr)[3], const size_t arr_size ) {
int* pbegin = arr;
int* pend = pbegin + arr_size;
while( pbegin != pend)
{
std::cout << *pbegin++ << std::endl;
}
}

Since the function isn't using iterators, I'd use the much more
natural:

for ( int i = 0 ; i < 3 ; ++ i ) {
std::cout << arr[ i ] << std::endl ;
}

It is an array, after all.
int main()
{
const size_t arr_size = 3;
int arr_3[3] = {10, 20, 30};
print_array( (&arr_3)[3], arr_size);

And what is (&arr_3)[3] supposed to mean, here? You take the
address of the array, so you have an int(*)[3]; a pointer to an
array of three ints. Then you use the [] operator to
dereference it; accessing the fourth array of three int's.
Except that since there is only one, you have undefined
behavior.

The function print_array takes a reference to an array of three
ints. You have an array of three ints. What more do you need?
return 0;
}

FWIW: this idiom is really only useful when the function is a
template, e.g.:

template< size_t N >
void
print_array( int const (&arr)[ N ] )
{
for ( size_t i = 0 ; i < N ; ++ i ) {
std::cout << arr[ i ] << std::endl ;
}
}

Done this way, it accepts all sizes, with the compiler
calculating the size each time.
 
F

Frank Birbacher

Hi!

James said:
Yes, there is no reference to an array of unknown size.

That's what g++ says, but I can't find the restriction in the
standard. Where does the standard says that something like: [code snip]
Is forbidden?

I ran Comeau:

Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
Copyright 1988-2007 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 4: error: parameter type involves reference to
array of unknown
bound
f( int (&a)[] )
^

I ran EDG/C++ on Dinkumware: It compiles. But on the following:

extern int arr[] ;

void
f( int (&a)[] )
{
}

void
g()
{
f( arr ) ;
}

int arr[] = {2, 3};

int main() {} //to shut up linker

The website went down. I don't know if that is my fault, though. o_O

No, it's back online and I reran the example:

sourceFile.cpp(11) : warning C4048: different array subscripts : 'int
(*)[]' and 'int (*)[2]'

So it's just a warning?!

Frank
 

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,260
Messages
2,571,039
Members
48,768
Latest member
first4landlord

Latest Threads

Top