4

In the following code I try to print all paths from the root to leaves in a Binary Tree. If I write a recursive function as follows :

    void printPath(BinaryTreeNode * n, int path[],int pathlen)
    {
    //assume base case and initializations taken care of

        path[pathlen++] = n->data;
        printPath(root->left,path,pathlen);
        printPath(root->right,path,pathlen);
    }

(I have purposefully removed base cases and edge cases handling to improve readability)

What happens to the path array? Is it just one global copy that gets modified during each recursive call ?Does the pathlen variable overwrites some of the path values, giving the feeling that each stack frame has it's own local copy of path, since pathlen is local to each stack frame?

Dubby
  • 1,154
  • 3
  • 16
  • 31
  • path is just a pointer variable, so whatever copy is made, they all must reference the same memory address. – Olayinka Jun 06 '14 at 19:39
  • This is a very long question: "Is it just one global copy that gets modified during each recursive call and the pathlen variable overwrites some of the path values giving the feeling that each stack frame has it's own local copy of path since pathlen is local to each stack frame?". You might wanna try to rephrase it a little bit, cause it's kinda hard to understand what you're asking at some point... – barak manos Jun 06 '14 at 19:39
  • 1
    @barakmanos I've tried to add comas wherever I could. Does that help? – Dubby Jun 06 '14 at 19:43

3 Answers3

3

Passing around a int[] variable is really almost like passing a int* around. The first invocation of the recursive function passes the real int[] which is nothing more than an address in memory, that's the same address used in every recursive call.

Basically if you place a debug print, eg

printf("%p\n", path);

in your recursive function you will see that the address is always the same, it doesn't change nor it gets modified. The only thing that is pushed onto the stack frame during the invocation is the address of the array, which nonetheless remains is always the same.

Jack
  • 131,802
  • 30
  • 241
  • 343
  • Could you also explain my doubt regarding the role of pathlen variable? Basically it is responsible for giving me complete path lens for sibling node? – Dubby Jun 06 '14 at 19:51
2

Welcome to array-pointer-decay. When you pass around an array, two distinct things happen:

  1. When you declare a function to take an array parameter, you are really defining the function to take a pointer parameter. I. e., the declaration

    void foo(int bar[]);
    

    is perfectly equivalent to

    void foo(int* bar);
    

    The declaration of the array has decayed into a declaration of a pointer to its first element.

  2. Whenever you use an array, it also decays into a pointer to its first element, so the code

    int baz[7];
    foo(baz);
    

    is again perfectly equivalent to

    int baz[7];
    foo(&baz[0]);
    

    There are only two exceptions, where this array-pointer-decay does not happen: the statements sizeof(baz) and &baz.

Together, these two effects create the illusion that arrays are passed by reference, even though C only ever passes a pointer by value.


The array-pointer-decay was invented to allow the definition of the array subscript operator in terms of pointer arithmetic: the statement baz[3] is defined to be equivalent to *(baz + 3). An expression which tries to add 3 to an array. But due to array-pointer-decay, baz decays into an int*, on which pointer arithmetic is defined, and which yields a pointer to the fourth element in the array. The modified pointer can then be dereferenced to get the value at baz[3].

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
1
void printPath(BinaryTreeNode * n, int path[],int pathlen);

compiler really looks at that like this

void printPath(BinaryTreeNode * n, int *path, int pathlen);

what happens to the path array? Is it just one global copy that gets modified during each recursive call

Nothing. The same path gets passed around, since in C array passing is just a pointer copy operation; and no, it isn't a global copy, but a parameter passed to the first call of the function, and will almost always live on the stack.

and the pathlen variable overwrites some of the path values giving the feeling that each stack frame has it's own local copy of path since pathlen is local to each stack frame?

Since you modify the value of the array elements and not the pointer pointing to the beginning of the array, nothing changes what path itself is pointing to (which is the array all the time). Like like you said it may give a feeling (particularly if you're used to that construct in other languages), but in reality only the same path gets passed around.

Aside: You don't seem to handle the exit condition and as it stands it'll be an infinite loop and mostly probably undefined behaviour when you start modifying elements that are out of the array's bounds.

legends2k
  • 31,634
  • 25
  • 118
  • 222
  • I'm taking care of the points you mentioned in 'Aside'. I just chose not to share it here for shorter code. – Dubby Jun 06 '14 at 19:47