7

Possible Duplicate:
length of array in function argument

Hi am doing homework and I am completly stumped. We were suppose to get every order of a list an array of integers so I wrote this piece of code, based off of my teacher's pseudocode:

void permute(int v[], int curr,char letters[])
{
    if(curr >= sizeof(v)/sizeof(int))
    {
        checkit(v,letters);
    }
    for(int i = curr; i < sizeof(v)/sizeof(int); i++)
    {
        swap(i,curr,v);
        permute(v,curr + 1,letters);
        swap(v[curr],v[i]);
    }//for
}//permu

The only thing I am not sure of is if sizeof(v)/sizeof(int) is the right way to go.

Community
  • 1
  • 1
Travis Pessetto
  • 3,260
  • 4
  • 27
  • 55
  • 3
    If your question is only about `sizeof(v)/sizeof(int)`, I would suggest editing your question title, because it's nothing to do with "recursion for permutations"... – Oliver Charlesworth Nov 24 '11 at 00:11

3 Answers3

9

sizeof(v)/sizeof(int) is not the way to go. Your function is exactly equivalent to:

void permute(int *v, int curr, char *letters)
{
    ...
}

i.e. v is not really an array, it's a pointer. You cannot pass arrays in C or C++.

The solution is one of the following (not exhaustive):

  • add an extra argument that explicitly describes the length of the array
  • add an extra argument that points at the last element of the array
  • use a proper container (e.g. std::vector), which you can call size() on
  • the template solution that @sehe suggests
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • +1 for containers, even though for homework they sometimes don't let you do it the "right" way. – Anthony Nov 24 '11 at 00:15
  • I thought you could - permute(int n[5]) is fine? The array isnt quite passed by value. But it is an array – Adrian Cornish Nov 24 '11 at 00:15
  • 1
    @Adrian: An array decays to a pointer when it's used as a function parameter. – Oliver Charlesworth Nov 24 '11 at 00:17
  • @Oli can you point me at the paragraph in the standard that says that (doesnt matter which C99, C++98, C++03, C11). Would it be 8.3.4.8 in C++ in C98 for example? [Example: consider int x[3][5]; Here x is a 3´5 array of integers. When x appears in an expression, it is converted to a pointer to (the first of three) fivemembered arrays of integers. In the expression x[i], which is equivalent to *(x+i), x is first converted to a pointer as described; then x+i is converted to the type of x, which involves multiplying i by the length of the object to which the pointer points, namely five... – Adrian Cornish Nov 24 '11 at 00:24
  • 2
    @Adrian: C99, 6.3.2.1, paragraph 3: "Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’". – Oliver Charlesworth Nov 24 '11 at 00:30
  • Thank Oli. It does indeed say that :-) – Adrian Cornish Nov 24 '11 at 00:33
  • Just a thanks, I decided to go with a vector and it is working much better. – Travis Pessetto Nov 24 '11 at 00:54
5

One of my pet peeves: you can get C++ to deduce the array size for you

template <size_t N>
void permute(int (&v)[N], int curr,char letters[])
{
    if(curr >= N)
    {
        checkit(v,letters);
    }
    for(int i = curr; i < N; i++)
    {
        swap(i,curr,v);
        permute(v,curr + 1,letters);
        swap(v[curr],v[i]);
    }//for
}//permu
sehe
  • 374,641
  • 47
  • 450
  • 633
0

In addition to Oli's answer: the typical way in C++ is to pass a pointer to the beginning and a pointer to the end of the sequence that you want to permute. By convention the beginning pointer is inclusive, the ending pointer is exclusive.

void permute(int *v, int *begin, int *end, char *letters) {
  if (begin == end) {
    checkit(v, end, letters);
  } else {
    ...
    permute(v, begin + 1, end, letters);
    ...
  }
}
Roland Illig
  • 40,703
  • 10
  • 88
  • 121