Problem understanding pass by value and pass by reference of arrays and what happens in the memory

Discussion in 'C++' started by venkatagmail, Oct 3, 2007.

  1. venkatagmail

    venkatagmail Guest

    I have problem understanding pass by value and pass by reference and
    want to how how they are or appear in the memory:

    I had to get my basics right again. I create an array and try all
    possible ways of passing an array. In the following code, fun1(int
    a1[]) - same as fun1(int* a1) - where both are of the type passed by
    reference. Inside this function, another pointer a1 is created whose
    address &a1 is different from that of the passed array a, which is &a
    in the main method. However, the addresses of a[0] and a[1] in the
    caller or main function are same as those of the array a1[0] and a1[1]
    in the called function fun1(int a1[]). Any modifications to the array
    in this function will reflect in the main method. How and where are
    these variables created in stack, heap, tables and what happens after
    and before calling the function?

    Lets look at the other function fun2(int *&a2) where I am trying to
    again pass by reference, but this time I do not want to create another
    pointer but directly work on the original pointer pointing to the
    array. When I pass this array a to this function it returns the
    following error which I did not understand

    fun2(a); // ERROR: invalid initialization of non-const reference of
    //type 'int*&' from a temporary of type 'int*'

    however, if I create another pointer int *aPtr = a; and then pass it
    as fun2(aPtr); it works fine. Also in this case, I am working directly
    with aPtr in both caller(main) and called (fun2) methods. i.e., &aPtr
    is same in the caller and called functions, &a2 in fun2(int* &a2),
    unlike the previous case, even this is pass by reference. I did not
    have time to figure out the problem, so I am posting it here for
    discussion and would like to know the details, as to how these
    variables are created or assigned in memory.


    #include<iostream>
    using namespace std;

    void fun1(int a1[]) // same as fun(int* p)
    {
    cout << "In fun(int a1[]) " << "a1 " << a1 << " &a1 " << &a1 << "
    &a1[0] " << &a1[0] << endl;
    // int a1[] is in a different location (different &a) but has the
    // correct addresses of a1[0] and a1[1]
    a1[0] = 10;
    a1[1] = 20;
    }

    void fun2(int* &a2)
    {
    cout << "In fun1(int* &a2) " << " a2 " << a2 << " &a2 " << &a2 << "
    &a2[0] " << &a2[0] << endl;
    a2[0] = 30;
    a2[1] = 50;
    }

    int main()
    {
    int a[2] = {0,1};
    cout << "Main: a " << a << " &a " << &a << " &a[0] " << &a[0] <<
    endl;

    //fun2(a); // ERROR: invalid initialization of non-const
    reference of
    //type 'int*&' from a temporary of type 'int*'
    fun1(a);
    cout << "After fun(a): " << a[0] << ' ' << a[1] << endl;

    int *aPtr = a;
    cout << "Passing aPtr whose &aPtr " << &aPtr << " aPtr " << aPtr
    << endl;
    fun2(aPtr); // Here it is ok, you can also use it as fun1(aPtr)
    cout << "After fun1(aPtr): " << a[0] << ' ' << a[1] << endl;

    int cInt = 10;
    //int* &cPtr = &cInt; // WRONG:logically wrong as you are trying
    to create a
    // non-const reference of type int* & from
    a
    // temporary of type int*
    int* cPtr = &cInt; // store the address of cInt in cPtr
    int* &cRefPtr = cPtr; // make a reference of the cPtr

    }

    output:

    Main: a 0x22ff80 &a 0x22ff80 &a[0] 0x22ff80
    In fun(int a1[]) a1 0x22ff80 &a1 0x22feb0 &a1[0] 0x22ff80
    After fun(a): 10 20
    Passing aPtr whose &aPtr 0x22ff7c aPtr 0x22ff80
    In fun1(int* &a2) a2 0x22ff80 &a2 0x22ff7c &a2[0] 0x22ff80
    After fun1(aPtr): 30 50
    venkatagmail, Oct 3, 2007
    #1
    1. Advertising

  2. venkatagmail

    Jim Langston Guest

    "venkatagmail" <> wrote in message
    news:...
    >I have problem understanding pass by value and pass by reference and
    > want to how how they are or appear in the memory:
    >
    > I had to get my basics right again. I create an array and try all
    > possible ways of passing an array. In the following code, fun1(int
    > a1[]) - same as fun1(int* a1) - where both are of the type passed by
    > reference. Inside this function, another pointer a1 is created whose
    > address &a1 is different from that of the passed array a, which is &a
    > in the main method. However, the addresses of a[0] and a[1] in the
    > caller or main function are same as those of the array a1[0] and a1[1]
    > in the called function fun1(int a1[]). Any modifications to the array
    > in this function will reflect in the main method. How and where are
    > these variables created in stack, heap, tables and what happens after
    > and before calling the function?
    >
    > Lets look at the other function fun2(int *&a2) where I am trying to
    > again pass by reference, but this time I do not want to create another
    > pointer but directly work on the original pointer pointing to the
    > array. When I pass this array a to this function it returns the
    > following error which I did not understand
    >
    > fun2(a); // ERROR: invalid initialization of non-const reference of
    > //type 'int*&' from a temporary of type 'int*'
    >
    > however, if I create another pointer int *aPtr = a; and then pass it
    > as fun2(aPtr); it works fine. Also in this case, I am working directly
    > with aPtr in both caller(main) and called (fun2) methods. i.e., &aPtr
    > is same in the caller and called functions, &a2 in fun2(int* &a2),
    > unlike the previous case, even this is pass by reference. I did not
    > have time to figure out the problem, so I am posting it here for
    > discussion and would like to know the details, as to how these
    > variables are created or assigned in memory.
    >
    >
    > #include<iostream>
    > using namespace std;
    >
    > void fun1(int a1[]) // same as fun(int* p)
    > {


    a1 is a local variable who's contents will be a pointer that is passed in.

    > cout << "In fun(int a1[]) " << "a1 " << a1 << " &a1 " << &a1 << "
    > &a1[0] " << &a1[0] << endl;


    Outputting a1 will output the contents of it, which is the pointer passed
    in, which points to the array a declared in main.
    Ouputting &a1 will output the address of the local pointer which is stored
    on the stack/heap.
    Outputting &a1[0] will output the address of the first int that a1 points
    to, which is the same as a1 itself.

    Lets presume a 4 byte int. When this function is called 4 bytes are set
    aside to hold the paramater a1 (or sizeof int*). Those 4 bytes can be
    anywhere in memory where the heap is (I believe compilers are free to use
    anywhere, heap is most common. I may be wrong on if they are free to use
    wherever or not. I don't have copy of standard). In your case it is memory
    locatoin 0x22feb0 to 0x22feb3. When this function is called and you pass
    the parameter of the pointer that pointer is pushed onto the stack. The
    function is called. The value is popped off and copied into the location of
    the local variable a1 (0x22feb0 to 0x22feb3). These 4 bytes in your case
    consist of the pointer value 0x22ff80.

    Now, if you look at the address of the variable a1 you will get 0x22f3b3.
    If you look at it's contents you will get 0x22ff80. If you dereference it
    (look at where the pointer is pointing to) you'll get the values in the
    array. Which is why &a1[0] returns the address of the original array.
    a1[0] says look at the 0th element of where the pointer is pointing to. &
    means get the address of it.

    Compilers are free to do somethings diffrent, I'm not aware of what they're
    allowed and not allowed to do different, but passing pointers is generally
    handled this way.

    > // int a1[] is in a different location (different &a) but has the
    > // correct addresses of a1[0] and a1[1]
    > a1[0] = 10;
    > a1[1] = 20;
    > }
    >
    > void fun2(int* &a2)
    > {
    > cout << "In fun1(int* &a2) " << " a2 " << a2 << " &a2 " << &a2 << "
    > &a2[0] " << &a2[0] << endl;
    > a2[0] = 30;
    > a2[1] = 50;
    > }
    >
    > int main()
    > {
    > int a[2] = {0,1};
    > cout << "Main: a " << a << " &a " << &a << " &a[0] " << &a[0] <<
    > endl;
    >
    > //fun2(a); // ERROR: invalid initialization of non-const
    > reference of
    > //type 'int*&' from a temporary of type 'int*'
    > fun1(a);
    > cout << "After fun(a): " << a[0] << ' ' << a[1] << endl;
    >
    > int *aPtr = a;
    > cout << "Passing aPtr whose &aPtr " << &aPtr << " aPtr " << aPtr
    > << endl;
    > fun2(aPtr); // Here it is ok, you can also use it as fun1(aPtr)
    > cout << "After fun1(aPtr): " << a[0] << ' ' << a[1] << endl;
    >
    > int cInt = 10;
    > //int* &cPtr = &cInt; // WRONG:logically wrong as you are trying
    > to create a
    > // non-const reference of type int* & from
    > a
    > // temporary of type int*
    > int* cPtr = &cInt; // store the address of cInt in cPtr
    > int* &cRefPtr = cPtr; // make a reference of the cPtr
    >
    > }
    >
    > output:
    >
    > Main: a 0x22ff80 &a 0x22ff80 &a[0] 0x22ff80
    > In fun(int a1[]) a1 0x22ff80 &a1 0x22feb0 &a1[0] 0x22ff80
    > After fun(a): 10 20
    > Passing aPtr whose &aPtr 0x22ff7c aPtr 0x22ff80
    > In fun1(int* &a2) a2 0x22ff80 &a2 0x22ff7c &a2[0] 0x22ff80
    > After fun1(aPtr): 30 50
    >
    Jim Langston, Oct 3, 2007
    #2
    1. Advertising

  3. venkatagmail

    venkatagmail Guest

    Thank you, as far as I understand from yours, correct me when I go
    wrong.

    when I start off with my declaration of an array 'a' in main(), they
    are created in the heap?, with a[0] ,a[1] pointing to my first and
    second elements of array a. The value of a contains the address of
    a[0] using which I use to pass as a pointer to an int to fun1(int
    a1[]). Before I call this function, all of my automatic variables move
    into stack and the address of the caller function is stored at the top
    of the stack to be returned to the operating system I believe?

    Once I enter the called method fun1(int a1[]) I have access to the
    first location of the array which is a[0] (which is already pushed
    into stack??) now stored in a1 (a1 is in a different location in
    heap), so once I make modifications to a1[0], am I making
    modifications to the original value in stack?? (which I know cannot be
    modified directly) or are these modified only after I exit the
    function fun1, which however is doubtful as a1[0], a1[1] and a[0],
    a[1] point to same address locations. I am confused how the memory
    thing takes place in case of pass by value, pass by reference using
    pointer and using a reference. This is just the beginning of my
    problem in understanding memory assignments. The original problem I
    posted above has lot more to ask.
    venkatagmail, Oct 3, 2007
    #3
  4. venkatagmail

    Barry Guest

    Re: Problem understanding pass by value and pass by reference ofarrays and what happens in the memory

    venkatagmail wrote:
    > I have problem understanding pass by value and pass by reference and
    > want to how how they are or appear in the memory:
    >
    > I had to get my basics right again. I create an array and try all
    > possible ways of passing an array. In the following code, fun1(int
    > a1[]) - same as fun1(int* a1) - where both are of the type passed by
    > reference. Inside this function, another pointer a1 is created whose
    > address &a1 is different from that of the passed array a, which is &a
    > in the main method. However, the addresses of a[0] and a[1] in the
    > caller or main function are same as those of the array a1[0] and a1[1]
    > in the called function fun1(int a1[]). Any modifications to the array
    > in this function will reflect in the main method. How and where are
    > these variables created in stack, heap, tables and what happens after
    > and before calling the function?
    >
    > Lets look at the other function fun2(int *&a2) where I am trying to
    > again pass by reference, but this time I do not want to create another
    > pointer but directly work on the original pointer pointing to the
    > array. When I pass this array a to this function it returns the
    > following error which I did not understand
    >
    > fun2(a); // ERROR: invalid initialization of non-const reference of
    > //type 'int*&' from a temporary of type 'int*'


    a is of array type, which is bound to a fixed address. so you can't
    change a to point to another one. when you pass an array as a parameter
    for a function, here a decays to type /int* const/, so you can convert
    it to /int*&/.

    >
    > however, if I create another pointer int *aPtr = a; and then pass it


    conversion from /int* const/ to /int*/ is allowed, /aPtr/ points to
    where /a/ points, but /aPtr/ has no way modify where /a/ points to.
    this is just like:

    const int S = 100;
    int i = S;

    > as fun2(aPtr); it works fine. Also in this case, I am working directly
    > with aPtr in both caller(main) and called (fun2) methods. i.e., &aPtr
    > is same in the caller and called functions, &a2 in fun2(int* &a2),
    > unlike the previous case, even this is pass by reference. I did not
    > have time to figure out the problem, so I am posting it here for
    > discussion and would like to know the details, as to how these
    > variables are created or assigned in memory.


    To understand these, you have learn how to find where the constness lays.

    as /aPtr/ is typeof 'int*' not 'int* const', then you can have /aPtr/
    point to anywhere of 'int' type, and of cause NOT to 'const int', as we
    can modify the content where /aPtr/ points to.

    >
    >
    > #include<iostream>
    > using namespace std;
    >
    > void fun1(int a1[]) // same as fun(int* p)
    > {
    > cout << "In fun(int a1[]) " << "a1 " << a1 << " &a1 " << &a1 << "
    > &a1[0] " << &a1[0] << endl;
    > // int a1[] is in a different location (different &a) but has the
    > // correct addresses of a1[0] and a1[1]
    > a1[0] = 10;
    > a1[1] = 20;
    > }
    >
    > void fun2(int* &a2)
    > {
    > cout << "In fun1(int* &a2) " << " a2 " << a2 << " &a2 " << &a2 << "
    > &a2[0] " << &a2[0] << endl;
    > a2[0] = 30;
    > a2[1] = 50;
    > }
    >
    > int main()
    > {
    > int a[2] = {0,1};
    > cout << "Main: a " << a << " &a " << &a << " &a[0] " << &a[0] <<
    > endl;
    >
    > //fun2(a); // ERROR: invalid initialization of non-const
    > reference of
    > //type 'int*&' from a temporary of type 'int*'
    > fun1(a);
    > cout << "After fun(a): " << a[0] << ' ' << a[1] << endl;
    >
    > int *aPtr = a;
    > cout << "Passing aPtr whose &aPtr " << &aPtr << " aPtr " << aPtr
    > << endl;
    > fun2(aPtr); // Here it is ok, you can also use it as fun1(aPtr)
    > cout << "After fun1(aPtr): " << a[0] << ' ' << a[1] << endl;
    >
    > int cInt = 10;
    > //int* &cPtr = &cInt; // WRONG:logically wrong as you are trying
    > to create a
    > // non-const reference of type int* & from
    > a
    > // temporary of type int*
    > int* cPtr = &cInt; // store the address of cInt in cPtr
    > int* &cRefPtr = cPtr; // make a reference of the cPtr
    >
    > }
    >
    > output:
    >
    > Main: a 0x22ff80 &a 0x22ff80 &a[0] 0x22ff80
    > In fun(int a1[]) a1 0x22ff80 &a1 0x22feb0 &a1[0] 0x22ff80
    > After fun(a): 10 20
    > Passing aPtr whose &aPtr 0x22ff7c aPtr 0x22ff80
    > In fun1(int* &a2) a2 0x22ff80 &a2 0x22ff7c &a2[0] 0x22ff80
    > After fun1(aPtr): 30 50
    >
    Barry, Oct 3, 2007
    #4
  5. venkatagmail

    venkatagmail Guest

    >>>"a is of array type, which is bound to a fixed address. so you can't
    change a to point to another one. when you pass an array as a
    parameter
    for a function, here a decays to type /int* const/, so you can convert
    it to /int*&/."<<<

    Barry, do you suggest that, I can convert array a bound to fixed
    address which decays to /int* const/ to type /int*&/ ??

    i.e., if I create an array int a[] = {1,2}; it is bound to a fixed
    address. If I pass it to a function fun2(int *&a2) it gives me an
    error!! Whereas I create another ptr /int* aPtr = a/, I can then pass
    it as this can now point to any integer and is not a constant value?

    >>>"conversion from /int* const/ to /int*/ is allowed, /aPtr/ points to

    where /a/ points, but /aPtr/ has no way modify where /a/ points to.
    this is just like:"<<<

    In line with what you said above, you say that I can create a pointer
    \int* aPtr = a;\ but you also say there is no way to modify where \a\
    points to?? But I can modify the contents of \a\ using the \aPtr\
    right or am I getting a wrong message here??

    What about the memory contents and how these are allocated for the
    three types of passing input arguments fun1(int a1[]) or fun1(int *a1)
    and fun2(int *&a2) ?? how different are these in terms how memory is
    allocated and assigned?
    venkatagmail, Oct 3, 2007
    #5
  6. venkatagmail

    Barry Guest

    Re: Problem understanding pass by value and pass by reference ofarrays and what happens in the memory

    venkatagmail wrote:
    >>>> "a is of array type, which is bound to a fixed address. so you can't

    > change a to point to another one. when you pass an array as a
    > parameter
    > for a function, here a decays to type /int* const/, so you can convert
    > it to /int*&/."<<<
    >
    > Barry, do you suggest that, I can convert array a bound to fixed
    > address which decays to /int* const/ to type /int*&/ ??
    >
    > i.e., if I create an array int a[] = {1,2}; it is bound to a fixed
    > address. If I pass it to a function fun2(int *&a2) it gives me an
    > error!! Whereas I create another ptr /int* aPtr = a/, I can then pass
    > it as this can now point to any integer and is not a constant value?
    >
    >>>> "conversion from /int* const/ to /int*/ is allowed, /aPtr/ points to

    > where /a/ points, but /aPtr/ has no way modify where /a/ points to.
    > this is just like:"<<<
    >
    > In line with what you said above, you say that I can create a pointer
    > \int* aPtr = a;\ but you also say there is no way to modify where \a\
    > points to?? But I can modify the contents of \a\ using the \aPtr\


    *where* /a/ points to can't be modified,
    *what* /a/ points to can be modified.

    int* aPtr = a;
    then you can modify *what* /a/ points to, /aPtr/ works just like a proxy;

    also, you can modify /aPtr/ to point to somewhere else like:

    int b[] = {1, 2};
    aPtr = b;
    now /aPtr/ is a proxy of /b/;

    > right or am I getting a wrong message here??
    >
    > What about the memory contents and how these are allocated for the
    > three types of passing input arguments fun1(int a1[]) or fun1(int *a1)
    > and fun2(int *&a2) ?? how different are these in terms how memory is
    > allocated and assigned?
    >


    Sorry.
    I think my words are not enough to explain these to you.

    see this example please.

    #include <iostream>
    #include <cstddef> // NULL

    void print(const int* a, int count)
    {
    for (int i = 0; i < count; ++i)
    std::cout << a << ' ';
    std::cout << std::endl;
    }

    void f1(int a[], int count) // == void f1(int* a, int count)
    {
    a[0] = 100; // modify WHAT a points to
    a = NULL; // a points to NULL (WHERE)
    print(a, count);
    }

    void f2(int* a, int count)
    {
    a[1] = 200;
    a = NULL;
    print(a, count);
    }

    int main()
    {
    int a[] = {1, 2, 3, 4};
    print(a, 4);
    f1(a, 4);
    f2(a, 4);
    print(a, 4);
    }
    Barry, Oct 3, 2007
    #6
  7. venkatagmail

    Barry Guest

    Re: Problem understanding pass by value and pass by reference ofarrays and what happens in the memory

    Barry wrote:
    > venkatagmail wrote:
    >>>>> "a is of array type, which is bound to a fixed address. so you can't

    >> change a to point to another one. when you pass an array as a
    >> parameter
    >> for a function, here a decays to type /int* const/, so you can convert
    >> it to /int*&/."<<<
    >>
    >> Barry, do you suggest that, I can convert array a bound to fixed
    >> address which decays to /int* const/ to type /int*&/ ??
    >>
    >> i.e., if I create an array int a[] = {1,2}; it is bound to a fixed
    >> address. If I pass it to a function fun2(int *&a2) it gives me an
    >> error!! Whereas I create another ptr /int* aPtr = a/, I can then pass
    >> it as this can now point to any integer and is not a constant value?
    >>
    >>>>> "conversion from /int* const/ to /int*/ is allowed, /aPtr/ points to

    >> where /a/ points, but /aPtr/ has no way modify where /a/ points to.
    >> this is just like:"<<<
    >>
    >> In line with what you said above, you say that I can create a pointer
    >> \int* aPtr = a;\ but you also say there is no way to modify where \a\
    >> points to?? But I can modify the contents of \a\ using the \aPtr\

    >
    > *where* /a/ points to can't be modified,
    > *what* /a/ points to can be modified.
    >
    > int* aPtr = a;
    > then you can modify *what* /a/ points to, /aPtr/ works just like a proxy;
    >
    > also, you can modify /aPtr/ to point to somewhere else like:
    >
    > int b[] = {1, 2};
    > aPtr = b;
    > now /aPtr/ is a proxy of /b/;
    >
    >> right or am I getting a wrong message here??
    >>
    >> What about the memory contents and how these are allocated for the
    >> three types of passing input arguments fun1(int a1[]) or fun1(int *a1)
    >> and fun2(int *&a2) ?? how different are these in terms how memory is
    >> allocated and assigned?
    >>

    >
    > Sorry.
    > I think my words are not enough to explain these to you.
    >
    > see this example please.
    >
    > #include <iostream>
    > #include <cstddef> // NULL
    >
    > void print(const int* a, int count)
    > {
    > for (int i = 0; i < count; ++i)
    > std::cout << a << ' ';
    > std::cout << std::endl;
    > }
    >
    > void f1(int a[], int count) // == void f1(int* a, int count)
    > {
    > a[0] = 100; // modify WHAT a points to


    oops:

    > a = NULL; // a points to NULL (WHERE)
    > print(a, count);


    print(a, count);
    a = NULL;
    > }
    >
    > void f2(int* a, int count)
    > {
    > a[1] = 200;
    > a = NULL;
    > print(a, count);


    print(a, count);
    a = NULL;

    > }
    >
    > int main()
    > {
    > int a[] = {1, 2, 3, 4};
    > print(a, 4);
    > f1(a, 4);
    > f2(a, 4);
    > print(a, 4);
    > }
    Barry, Oct 3, 2007
    #7
  8. venkatagmail

    venkatagmail Guest

    Thank you Barry for making me realize the problem of const and non-
    const reference and pointers. I wished I also understood how the
    memory is allocated in detail when calling these different methods.
    I have problems understanding linked lists where I pass a head node
    pointer by value and by reference. In either case I am able to access
    the all the subsequent nodes until the end of the list, delete and
    make modifications to them in the called function. I still want to
    understand these things in terms of the memory allocation and
    deallocation in heap and stack.
    venkatagmail, Oct 3, 2007
    #8
  9. venkatagmail

    Jim Langston Guest

    "venkatagmail" <> wrote in message
    news:...
    >>>>"a is of array type, which is bound to a fixed address. so you can't

    > change a to point to another one. when you pass an array as a
    > parameter
    > for a function, here a decays to type /int* const/, so you can convert
    > it to /int*&/."<<<
    >
    > Barry, do you suggest that, I can convert array a bound to fixed
    > address which decays to /int* const/ to type /int*&/ ??
    >
    > i.e., if I create an array int a[] = {1,2}; it is bound to a fixed
    > address. If I pass it to a function fun2(int *&a2) it gives me an
    > error!! Whereas I create another ptr /int* aPtr = a/, I can then pass
    > it as this can now point to any integer and is not a constant value?
    >
    >>>>"conversion from /int* const/ to /int*/ is allowed, /aPtr/ points to

    > where /a/ points, but /aPtr/ has no way modify where /a/ points to.
    > this is just like:"<<<
    >
    > In line with what you said above, you say that I can create a pointer
    > \int* aPtr = a;\ but you also say there is no way to modify where \a\
    > points to?? But I can modify the contents of \a\ using the \aPtr\
    > right or am I getting a wrong message here??
    >
    > What about the memory contents and how these are allocated for the
    > three types of passing input arguments fun1(int a1[]) or fun1(int *a1)
    > and fun2(int *&a2) ?? how different are these in terms how memory is
    > allocated and assigned?


    There is no differnce. In all cases an address is pushed onto the stack and
    popped off by the function. It's just how the compiler treates them that is
    different.
    Jim Langston, Oct 3, 2007
    #9
  10. venkatagmail

    Barry Guest

    Re: Problem understanding pass by value and pass by reference ofarrays and what happens in the memory

    venkatagmail wrote:
    > Thank you Barry for making me realize the problem of const and non-
    > const reference and pointers. I wished I also understood how the
    > memory is allocated in detail when calling these different methods.
    > I have problems understanding linked lists where I pass a head node
    > pointer by value and by reference. In either case I am able to access


    pass by reference IIF you create the list inside the function body,
    then you assign the "created pointer to root" to the passed in
    reference, then the function caller gain the side-effect, the passed in
    parameter then points to the created list. after calling the function.

    in C, we often use pointer to pointer for this goal.

    > the all the subsequent nodes until the end of the list, delete and
    > make modifications to them in the called function. I still want to
    > understand these things in terms of the memory allocation and
    > deallocation in heap and stack.
    >


    When accessing modifying the list you can only pass in the pointer to
    the list only. As you don't change the passed in pointer to point to
    another list(actually a node).


    I have an idea for you,
    You can use a debugger, like Visual C++, then you can see the the object
    lays and how. Pay attention to when/what the variable is
    assigned/initialized.

    on reference, it's special, you can jump to the assembly code.
    I was told that VC uses pointer-like stuff to implement it.

    http://www.parashift.com/c -faq-lite/references.html

    TC++PL:
    "In some cases, the compiler can optimize away a reference so that there
    is no object representing that reference at runtime."

    Reference is special, remember.


    Here is exmaple when reference to pointer is used:

    #include <iostream>
    #include <cstddef> // NULL

    int g_arr[] = {1, 2, 3};

    void get_array(int*& arr, int& count)
    {
    arr = g_arr;
    count = 3;
    }

    void print(const int* a, int count)
    {
    for (int i = 0; i < count; ++i)
    std::cout << a << ' ';
    std::cout << std::endl;
    }

    int main()
    {
    int count = 0;
    int* pi = NULL;
    get_array(pi, count);
    print(pi, count);
    }
    Barry, Oct 3, 2007
    #10
  11. venkatagmail

    James Kanze Guest

    On Oct 3, 2:59 am, "Jim Langston" <> wrote:
    > "venkatagmail" <> wrote in message
    > news:...


    [...]
    > > void fun1(int a1[]) // same as fun(int* p)
    > > {


    > a1 is a local variable who's contents will be a pointer that is passed in.


    And a1 has type int* a, despite the way it is written.

    > > cout << "In fun(int a1[]) " << "a1 " << a1 << " &a1 " << &a1 << "
    > > &a1[0] " << &a1[0] << endl;


    > Outputting a1 will output the contents of it, which is the pointer passed
    > in, which points to the array a declared in main.
    > Ouputting &a1 will output the address of the local pointer which is stored
    > on the stack/heap.
    > Outputting &a1[0] will output the address of the first int that a1 points
    > to, which is the same as a1 itself.


    > Lets presume a 4 byte int. When this function is called 4
    > bytes are set aside to hold the paramater a1 (or sizeof int*).
    > Those 4 bytes can be anywhere in memory where the heap is (I
    > believe compilers are free to use anywhere, heap is most
    > common.


    I think you mean stack. Except, of course, that in a lot of
    cases, function arguments are passed in registers. It's only
    when he takes its address that the compiler generates a local
    variable (typically on the stack) for it, and copies the
    register into that. (Also, while the machines I use do have
    four byte int's, int* is 8 bytes on all of them. Not that it
    matters.)

    > I may be wrong on if they are free to use
    > wherever or not. I don't have copy of standard).


    The standard only describes the behavior of legal programs.
    (And the only time it speaks of stack or heap are in the library
    sections, concerning library classes or functions---where "heap"
    has a completely different meaning.) Anything the compiler does
    is legal as long as the resulting program has the "observable
    behavior" resulting from the behavior described in the standard.

    > In your case it is memory
    > locatoin 0x22feb0 to 0x22feb3. When this function is called and you pass
    > the parameter of the pointer that pointer is pushed onto the stack. The
    > function is called. The value is popped off and copied into the location of
    > the local variable a1 (0x22feb0 to 0x22feb3). These 4 bytes in your case
    > consist of the pointer value 0x22ff80.


    If the argument is already on the stack, all the compilers I
    know will use it there. The only time it gets copied into a
    local variable is when it was passed by register.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Oct 3, 2007
    #11
  12. venkatagmail

    James Kanze Guest

    On Oct 3, 6:22 am, venkatagmail <> wrote:
    > >>>"a is of array type, which is bound to a fixed address. so you can't


    > change a to point to another one. when you pass an array as a
    > parameter
    > for a function, here a decays to type /int* const/, so you can convert
    > it to /int*&/."<<<


    I don't like the word "decays" here (although I know it is quite
    common). It implicitly converts to, in the same way an int will
    implicitly convert to a double. The important thing to remember
    (here) is that the pointer is a new, temporary object.

    > Barry, do you suggest that, I can convert array a bound to fixed
    > address which decays to /int* const/ to type /int*&/ ??


    That's not the problem. The types match. The problem is that
    you cannot initialize a reference to non-const with a temporary,
    and the result of your conversion is a temporary. This is a
    separate rule, outside the type system, which applies to the
    initialization of a reference.

    > i.e., if I create an array int a[] = {1,2}; it is bound to a
    > fixed address. If I pass it to a function fun2(int *&a2) it
    > gives me an error!! Whereas I create another ptr /int* aPtr =
    > a/, I can then pass it as this can now point to any integer
    > and is not a constant value?


    Because a named variable is not a temporary. (The standard
    actually speaks in terms of rvalues and lvalues, but it comes
    out to the same thing here, at least with non class types: a
    temporary is an rvalue, i.e. a pure value, without an address.)

    [..]
    > What about the memory contents and how these are allocated for the
    > three types of passing input arguments fun1(int a1[]) or fun1(int *a1)
    > and fun2(int *&a2) ?? how different are these in terms how memory is
    > allocated and assigned?


    The first two are identical: "fun1(int* a)". Given a pointer to
    an int (whether it is the result of an implicit array to pointer
    conversion, or otherwise, makes no difference), the compiler
    uses the value of the argument (the rvalue) to initialize the
    function argument (which may be in a register, or on the stack).
    The third says that you are passing a reference to the pointer,
    and that the pointer may be changed via this reference.
    Typically, the compiler implements this by passing the address
    of the argument---the address of the pointer, here. Since the
    result of a conversion is a pure value, the compiler would have
    to artificially generate an object (with pointer type) to hold
    it, and pass the address of this object. In fact, the standard
    forbids this.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Oct 3, 2007
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. NM
    Replies:
    6
    Views:
    444
    Default User
    Sep 20, 2006
  2. Replies:
    1
    Views:
    457
    Mark Rae [MVP]
    Sep 20, 2007
  3. Philipp
    Replies:
    21
    Views:
    1,093
    Philipp
    Jan 20, 2009
  4. ericnoonan
    Replies:
    0
    Views:
    330
    ericnoonan
    Dec 14, 2009
  5. MG
    Replies:
    5
    Views:
    176
    Thomas 'PointedEars' Lahn
    Apr 16, 2010
Loading...

Share This Page