Hello,

I have this code:

#include<stdio.h>

int q = 10;

void fun(int *p){
    *p = 15;
    p = &q; 
    printf("%d ",*p);
}    

int main(){

  int r = 30;
  int *p = &r;  
  fun(p);
  printf("%d", *p);
  return 0;
}

which returns 10 15

I can't understand why it doesn't return 10 10

int q = 10;

void fun(int *p)
{
    *p = 15; // after this point, the 'int' at the address passed in holds 15
    p = &q; // NOW ... p holds a different address, the address of global q
    printf("%d ",*p);
}    

Edited 9 Months Ago by David W

I suspect the confusion is the name p. You have two variables with the name p, which in this case is perfectly acceptable. However, it might be that you're seeing them as the same object, which is false. Consider this modification to fun:

void fun(int *meep){
    *meep = 15;
    meep = &q; 
    printf("%d ",*meep);
}

This definition is equally valid, and now it's more obvious that p and meep are completely independent objects that just happen to contain the same address as their value.

Now, with this modification, see if you can figure out why your result is 10 15. :)

I understand both your examples but I can't understand why the printf statement in main prints 15 and not 10 ,since after calling fun ,p pointer's value (*p) points to q which is 10.

This definition is equally valid, and now it's more obvious that p and meep are completely independent objects that just happen to contain the same address as their value.

So,since they contain the same address shouldn't they contain the same value?

Thank you !

Edited 9 Months Ago by glao

Try this ... expanding on Dani's @deceptikon's hint of 'using better variable names'

/* pointer_demo.c */

#include<stdio.h>

/* global */
int q_global = 10;

void func( int* );


int main()
{
    int r = 30;
    int* r_address = &r;
    func( r_address ); /* after this call, value at r_address is set to 15 */
    printf( "%d", *r_address ); /* prints 15 */
    return 0;
}


void func( int* address_copy )
{
    *address_copy = 15; /* set value at (calling) address to 15 */
    address_copy = &q_global; /* update address_copy to NOW hold address of int  q_global */
    printf( "%d ", *address_copy ); /* print value at address_copy, i.e. value of q_global */
}

Edited 9 Months Ago by David W

func( r_address ); /* after this call, value at r_address is set to 15 */

Ok , until here , we agree.Value is set to 15.And it is set to 15 because r_address inherits the same value as address_copy,which is 15.But, right after *address_copy = 15;
we have address_copy = &q_global; ,so now address_copy and r_address should both have the value 10.

NOT SO! --- > address_copy and r_address should both have the value 10.

address_copy holds an address ... A new address now ... the address of q_global.

address_copy holds an address ... A new address now ... the address of q_global.

Yes, and it is 10 . But where the 15 came from ?

When I pass the r_address in func , won't it take the address_copy address?Hence, the address of q_global?

You are missing completely the idea of 'address' as opposed to the 'value' stored at some address.

A pointer variable ONLY holds addresses!

At machine level ... you can go to an address and get the value there (direct addressing)

Or ... (for indirect addressing )
you can go to an address ... get the address stored there and then go to that address to get the value stored that final address.

Edited 9 Months Ago by David W

Ok, I know that .My problem is at the moment I am out of the function func,doesn't p points to q address and hence value 10?

If we compare to a swap function for example , swap(a,b) , where a and b pointers and in main I have a=10,b=3 ,when I call swap the values are changed according to function.

In our case?Inside func p points to q and has value 10.In main it has value 30 but it is changed since the function func is called.

Your problem is that you suppose you understand ... BUT you do NOT yet!
If you wish to learn about this issue ...
you must first admit that you presently hold some wrong idea(s) here.

I suggest that you write (your own debugging ) code ... to print out all the addresses ... and the values at EACH address ... at each step as the program logic flows.

Then (maybe?) you might see what is happening at each step.

Edited 9 Months Ago by David W

Ok ... let's suppose that you have had time by now to write and try out some 'debugging' type code ... as per my suggestion above ... but maybe ... you still fail to 'see' the answer to your problem ... and the solution to the very commom and related problem?

What follows is a demo of two ways to handle this (related) problem ... the problem of changing addresses inside functions ... addresses held by passed in pointers ... and the solution to the problem of how to reflect, in the calling scope, this address update.

/* pointer_demo.3 */

#include <stdio.h>


int q_global = 10;

int* func1( int* address_copy ); /* returns any updates to address inside fumction */

void func2( int** pp ); /* a pointer to a pointer */




int main()
{
    /* method 1 */
    int r = 30;
    int* r_address = &r;
    puts( "Method 1 ..." );

    printf( "q_global = %d, &q_global = %p\n", q_global, (void*) &q_global );
    printf( "r = %d, r_address = %p\n", r,  (void*)r_address );

    r_address = func1( r_address );

    printf( "%d\n", *r_address );
    printf( "r = %d, r_address = %p\n", r,  (void*)r_address );


    /* method 2 */
    puts( "\nMethod 2 ..." );
    r = 30;
    r_address = &r;

    printf( "q_global = %d, &q_global = %p\n", q_global, (void*) &q_global );
    printf( "r = %d, r_address = %p\n", r,  (void*)r_address );

    func2( &r_address ); /* NOTE: here we pass in the address of the pointer variable r_address */

    printf( "%d\n", *r_address );
    printf( "r = %d, r_address = %p\n", r,  (void*)r_address );

    return 0;
}




int* func1( int* address_copy )
{
    *address_copy = 15; 
    printf( "%d ", *address_copy );
    address_copy = &q_global; 
    printf( "%d ", *address_copy );

    return address_copy; /* return the newly changed address, so that the new address gets updated in the calling scope */
}

void func2( int** pp )
{
    **pp = 15;
    printf( "%d ", **pp );
    *pp = &q_global; /* update here the 1st level of indirection, so that refelcted in calling scope */
    printf( "%d ", **pp );
}

Edited 9 Months Ago by David W

First of all thank you very much for your help..

Your problem is that you suppose you understand ... BUT you do NOT yet! If you wish to learn about this issue ...you must first admit that you presently hold some wrong idea(s) here.

Of course, I admit it!Since I can't figure..I thought this was clear :)

So , checking your code ( I just come back to this problem , I haven't studied since yesterday ,so you wrote the code first)

   r_address = func1( r_address );
    printf( "%d\n", *r_address );
    printf( "r = %d, r_address = %p\n", r,  (void*)r_address );

The first print shows the value 10 and I agree since r_address holds q_global address.
But , in the second print I would expect r to have value 10 and not 15 ,since int* r_address = &r; .The r_address has changed and the pointer value also (*r_address is 10). Why r doesn't change?

And a weird thing.In my first post ,after calling the function , the *p has value 15 ,but in your example it has value 10 !I can't understand!

EDIT:

I just saw that changing to :

void func1( int* address_copy )
{
    *address_copy = 15; 
    printf( "%d ", *address_copy );
    address_copy = &q_global; 
    printf( "%d ", *address_copy );
}

    func1( r_address );

    printf( "%d\n", *r_address );

printf( "r = %d, r_address = %p\n", r,  (void*)r_address );

Then , I get the value 15 for *r_address and the r_address is not updated to point to q_global address.Why is not updated?

An example:

#include <stdio.h>


void swap(int* a, int* b)
{
 int temp = *a;
 *a = *b;
 *b = temp;


}


int main()
{
 int x = 5, y = 10;
 int *a = &x, *b = &y;
 swap(a, b);
 printf("%d %d\n", *a, *b);
}

Here,the values a and b are updated after function call as they should.
What is going on on our example?What is that I can't see????

Sorry about all the confusion..

Edited 9 Months Ago by glao

r_address = func1( r_address );

Note in the above func1, we are (now) returning
(via the return statement in func1)
the changed address.

So then ...
after the returned new address value ...
the name 'r_address' is a 'mis-nomer'.

If you ran the code example ... and studied the output ... you would see this confirmed.

Below is a (simplified, but) related example ... do you 'see' how it is 'related'?
(Hint ... pointer keeps holding new addresses.)

/* pointer_demo4.c */


#include <stdio.h>



int main()
{
    const int ary[] = { 1, 2, 3 };
    const int ary_size = sizeof ary / sizeof *ary;

    const int* p = ary; /* p now holds address to first byte in ary ... */

    printf( "At START: p = \n%p \nand &ary[0] = \n%p\n", (void*) p, (void*) &ary[0] );

    int i;
    for( i = 0; i < ary_size; ++ i )
    {
        p = &ary[i]; /* p keeps getting new addresses ... */
        printf( "%d ", *p );
    }

    printf( "At END: p = \n%p \nand &ary[0] = \n%p\n", (void*) p, (void*) &ary[0] );


    return 0;
}

Edited 9 Months Ago by David W

So ... can you now 'see' what is happening and why ?

In each of ...

1) your original version (address change inside function NOT reflected in calling scope)

and ...

2) each of the 2 recent modified examples that return the address changes inside the function to the calling scope

Here is a practical example:
(Note: you need all 3 files in the same folder to compile the .c file... See the comments in the .h file to obtain link to download copy of file "readLine.h")

/* CvecOfString2.h */ /* this version 2016-02-18 */


#ifndef dwCvec_H
#define dwCvec_H

#include "readLine.h"
/*
    Note: file "readline.h" is available at this next link ...

    http://developers-heaven.net/forum/index.php/topic,2580.msg2864.html#msg2864
*/



/* re-set this starting num of rec's to minimize realloc's */
#ifndef VEC_CHUNK_SIZE
#define VEC_CHUNK_SIZE 8
#endif

typedef struct myCvecOfString
{
    char** ary;
    int size;
    int cap; /* capacity*/
} CvecOfString;


/* with these, an address is passed, so NO copy made and/or original updated */
void initCvecOfString( CvecOfString* ); /* sets ary to NULL and size, cap to 0 */
void push_backCvecOfString( CvecOfString*, char* );
void enlargeCvecOfString( CvecOfString* );
void reserveCvecOfString( CvecOfString*, int );
void clearCvecOfString( CvecOfString* );


void initCvecOfString( CvecOfString* cv )
{
    cv->ary = NULL;
    cv->size = cv->cap = 0;
}

void push_backCvecOfString( CvecOfString* cv, char* str )
{
    if( cv->size == cv->cap ) enlargeCvecOfString( cv );

    /* now add in new Rec ... */
    cv->ary[cv->size] = str; /* just copy pointer over */

    ++ cv->size;
}

/* new array to hold 2x's records ... copies old to new */
void enlargeCvecOfString( CvecOfString* cv )
{
    void* tmp;
    if( cv->cap ) cv->cap += cv->cap; /* double capacity ... */
    else cv->cap = VEC_CHUNK_SIZE; /* set initial capacity */
    tmp = realloc( cv->ary, cv->cap * sizeof(char*) );
    if( tmp == NULL )
    {
        clearCvecOfString( cv );
        myAssert( 0, "Error: realloc failed in enlargeCvec..." );
    }
    /* else ... */
    cv->ary = tmp; /* update the base address of cv->ary */
}

void reserveCvecOfString( CvecOfString* cv, int newCap )
{
    if( newCap > cv->cap )
    {
        void* tmp;
        cv->cap = newCap;
        tmp = realloc(cv->ary, cv->cap * sizeof(char*) );
        if( tmp == NULL )
        {
            clearCvecOfString( cv );
            myAssert( 0, "Error: realloc failed in reserveCvec..." );
        }
        /* else ... */
        cv->ary = tmp; /* update the base address of cv->ary */
    }
}

void clearCvecOfString( CvecOfString* cv )
{
    if( cv->size )
    {
        int i;
        for( i = cv->size-1; i >- 0; -- i )
            free( cv->ary[i] );

        free( cv->ary );
        initCvecOfString( cv );
    }
}


#endif

And the test program:

/* test_CvecOfString2.c */


#include "CvecOfString2.h" /* includes "readLine.h" */



int main()
{
    const char* ary[] = { "Sam", "8ill", "Jane", "Anne", "George", "Millie",
                          "Bob", "Peter", "Penny" };
    const int size = sizeof ary / sizeof *ary;

    CvecOfString cv;
    initCvecOfString( &cv );

    int i;
    for( i = 0; i < size; ++ i )
    {
        push_backCvecOfString( &cv, newCopy(ary[i]) ); /* newCopy is also included in file "readLine.h" */
    }

    for( i = 0; i < cv.size; ++ i )
    {
        printf( "%s ", cv.ary[i] );
    }

    printf( "\ncv.cap = %d, cv.size = %d", cv.cap, cv.size );


    clearCvecOfString( &cv );
    printf( "\ncv.cap = %d, cv.size = %d", cv.cap, cv.size );


    printf( "\n\nPress 'Enter' to continue/exit ... " );
    getchar();
    return 0;
}

Edited 9 Months Ago by David W

So ... can you now 'see' what is happening and why ?

Unfortunately ,no!
In my example there is no pointer increment or value increment.

I didn't understand how the practical example you posted will help me.

The example involves allocating (sometines changed new starting addresses) new enlarged memory blocks ... to hold a (dynamic) array of a growing number of elements (in the example, the elements are each dynamic C strings ... each string may be of any length). The program shows a way to easily manage all those (changing dynamic) memory needs.

The changes inside, for example, the push_back function, are reflected to the calling scope.

You do NOT reflect the address change inside the below function to the calling scope!

/* pointer_demo5.c */

#include <stdio.h>

int q = 10;


void fun( int* p ) /* Note this 'p' is an 'alias' (i.e. a copy in it's own memory, NOT the same memory as of 'p' outside in 'main' ) */
{
    *p = 15;
    p = &q;
    printf( "%d ",*p );
}



int main()
{
    int r = 30;
    int* p = &r;

    fun(p); /* the 1st thing done inside function 'fun' is to set 'r' in 'main' to 15 */
    /* the next thing done inside ... is to set p to point to global q of 10 */
    /* the next thing is to print q = 10 */


    /* what is (this) 'p' pointing to now ? ... ANSWER: it is *STILL* pointing to 'r' which NOW holds 15 */
    /* WHY? Only a copy inside was changed ... but the changes to that copy were NOT reflected back to the calling scope! */
    printf( "%d", *p );

    return 0;
}

Edited 9 Months Ago by David W

Ok, I agree with all the comments.

But , what is the difference then with the swap function I wrote above?
Why there the pointer values are changed?

#include <stdio.h>

/* Note: inside we do NOT change a or b ... 
     i.e. NO addresses get changed.
      We only change the dereferenced values. */
void swap( int* a, int* b ) /* a, b are 'local copies' ... */
{
    int tmp = *a; /* ok, address pointed to (i.e. &x is here dereferenced) */
    *a = *b; /* x is set to y */
    *b = tmp; /* y is set to tmp, i.e. original value held by x */
}

int main() /* simplified */
{
    int x = 5, y = 10;
    swap( &x, &y ); /* taking addresses */
    printf( "%d %d\n", x, y );
    return 0;
}

Edited 9 Months Ago by David W

I am really stuck here!!!! ......................................

I can't see it sorry .I appreciate your help .I will check it again tomorrow...

I can't get that since we are changing the address of p ( it point to q global ) inside function and the q global has value 10 why is not reflected to main.

Note the words 'local' ... and 'copy' (of pointer/address) ...

This is the crux of your problem here.

int a = 1, b = 2;
int* x = &a;
int* y = x; /* an alias (i.e. a copy) of x */
x = &b;
/* what is *y = ? now */
/* what is *x = ? now */

Compile and run ...

#include <stdio.h>

int main()
{
    int a = 1, b = 2;
    int* x = &a;
    int* y = x; /* an alias (i.e. a copy) of x */
    x = &b;

    /* what is *y = ? now */
    printf( "*y = %d ", *y );

    /* what is *x = ? now */
    printf( "*x = %d", *x );

    return 0;
}

Edited 9 Months Ago by David W

Ok, I understand your last example with the copy.
I will try tomorrow to see how it is connected to my problem.

Thanks again!

So , as I understand , we change only the value of the pointer but not it's address , that's why in main shows 15.

But , I wrote this:

#include <stdio.h>

int glob = 9;

void test( int *k )
{
    *k =12;
    k = &glob;
}


int main()
{

    int a = 2;
    int *ptr = &a;

    test(ptr);

    printf("ptr = %d\t ptr_addr = %p",*ptr,ptr);
    printf("\n\na= %d\t a_addr = %p\n",a,&a);


    return 0;
}

and here both a and *ptr are updated and have the same value and address.What is the difference with our problem?

I am almost there!

I wrote this:

#include <stdio.h>

        int glob = 9;

        void test( int **k )
        {
            **k =12;
            *k = &glob;
            printf("Inside function k = %d\tk_addr = %p\n",**k,*k);
        }


        int main()
        {

            int a = 2;
            int *ptr = &a;

            test(&ptr);

            printf("ptr = %d\t ptr_addr = %p",*ptr,ptr);
            printf("\n\na = %d\t a_addr = %p\n",a,&a);


            return 0;
        }

So, I am ok with everything except that I would expect a also to hold the value of ptr ( hence 9 ) .

This doesn't happen because ptr 's value and address is changed inside the function?So , it is a scope problem?

Edited 9 Months Ago by glao

This article has been dead for over six months. Start a new discussion instead.