passing an unbounded array to a function

I'm trying to take an arbitrary-length array into a function (bubble sort used here as an example)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void bubblesort(int (&listy)[]){
  int length = (sizeof(listy)/sizeof(*listy));
  bool sorted = false;
  int holder;
  int tail;
  while (!sorted){
    sorted = true;
    tail = 1;
    for(int c = 0; c < (length-tail); c++){
      if(listy[c] < listy[c+1]){
	sorted = false;
	holder = listy[c];
	listy[c] = listy[c+1];
	listy[c+1] = holder;
      }
    }
  }
}


But it fails to compile with
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
In file included from sorttest.cpp:1:0:
sort.h:1:31: error: parameter 'listy' includes reference to array of unknown bound 'int []'
 void bubblesort(int (&listy)[]){
                               ^
sort.h: In function 'void bubblesort(int (&)[])':
sort.h:2:29: error: invalid application of 'sizeof' to incomplete type 'int []'
   int length = (sizeof(listy)/sizeof(*listy));
                             ^
sorttest.cpp: In function 'int main()':
sorttest.cpp:6:17: error: invalid initialization of reference of type 'int (&)[]' from expression of type 'int [10]'
   bubblesort(moo);
                 ^
In file included from sorttest.cpp:1:0:
sort.h:1:6: error: in passing argument 1 of 'void bubblesort(int (&)[])'
 void bubblesort(int (&listy)[]){
      ^
Declare parameters of the function as

void bubblesort( int listy[], siize_t size ){

where size is the array size.
The length of the array is part of the array type so you can't leave it out when passing the array by reference. What you could do is passing a pointer to the first element in the array:
 
void bubblesort(int listy[]){
or
 
void bubblesort(int* listy){

(Even if they look different both ways are exactly the same)
this solution destroys the array

edit: oops, it didn't destroy the array, I was just reading it incorrectly
Last edited on
What solution does destroy the array?!
You can get the array reference approach to work if you make the function a template (with the length as a parameter.) But:

1. the int[] plus length approach makes more sense if you're going to have lots of different sizes of array, as the template based approach will result in different versions of the function being instantiated.

2. the template based approach will only work with actual arrays; it cannot be used with dynamically allocated arrays.

Andy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <iostream>
#include <cstdlib>
using namespace std;

template<int length>
void bubblesort_tmpl(int (&listy)[length]){
  bool sorted = false;
  int holder;
  int tail;
  while (!sorted){
    sorted = true;
    tail = 1;
    for(int c = 0; c < (length-tail); c++){
      if(listy[c] < listy[c+1]){
    sorted = false;
    holder = listy[c];
    listy[c] = listy[c+1];
    listy[c+1] = holder;
      }
    }
  }
}

void bubblesort_len(int listy[], int length){
  bool sorted = false;
  int holder;
  int tail;
  while (!sorted){
    sorted = true;
    tail = 1;
    for(int c = 0; c < (length-tail); c++){
      if(listy[c] < listy[c+1]){
    sorted = false;
    holder = listy[c];
    listy[c] = listy[c+1];
    listy[c+1] = holder;
      }
    }
  }
}

int main(){
    const int seed = 123; // fixed seed for testing...
    const int datasize = 16;
    int data[datasize];

    // with template approach
    srand(seed);
    for(int i = 0; i < datasize; ++i) {
        data[i] = ((rand() % 10) + 1);
    }
    bubblesort_tmpl(data);
    cout << "bubblesort_tmpl = ";
    for(int i = 0; i < datasize; ++i) {
        cout << " " << data[i];
    }
    cout << endl;

    // with length approach
    srand(seed);
    for(int i = 0; i < datasize; ++i) {
        data[i] = ((rand() % 10) + 1);
    }
    bubblesort_len(data, datasize);
    cout << "bubblesort_len  = ";
    for(int i = 0; i < datasize; ++i) {
        cout << " " << data[i];
    }
    cout << endl;

    int* pdata = new int[datasize];

#ifdef FAILS_TO_COMPILE
    // with template approach
    srand(seed);
    for(int i = 0; i < datasize; ++i) {
        data[i] = ((rand() % 10) + 1);
    }
    bubblesort_tmpl(pdata);
    cout << "bubblesort_tmpl = ";
    for(int i = 0; i < datasize; ++i) {
        cout << " " << pdata[i];
    }
    cout << endl;
#endif // FAILS_TO_COMPILE

    // with length approach
    srand(seed);
    for(int i = 0; i < datasize; ++i) {
        pdata[i] = ((rand() % 10) + 1);
    }
    bubblesort_len(pdata, datasize);
    cout << "bubblesort_len  = ";
    for(int i = 0; i < datasize; ++i) {
        cout << " " << data[i];
    }
    cout << endl;

    delete [] pdata;

    return 0;
}


bubblesort_tmpl =  10 10 10 9 7 6 6 5 5 4 4 4 1 1 1 1
bubblesort_len  =  10 10 10 9 7 6 6 5 5 4 4 4 1 1 1 1
bubblesort_len  =  10 10 10 9 7 6 6 5 5 4 4 4 1 1 1 1
Last edited on
You could have an inline function template calling the function with the correct length.

1
2
3
4
5
6
7
void bubblesort( int listy[], siize_t size );

template<int length>
inline void bubblesort(int (&listy)[length])
{
	bubblesort(listy, length);
}
The best of both worlds!

Andy
Topic archived. No new replies allowed.