hi , i'm having a problem with pointers in C ...

Discussion in 'C' started by blackslither, Oct 26, 2008.

  1. blackslither

    blackslither New Member

    Joined:
    Oct 26, 2008
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    0
    I will give a simple example inspired from my problem :

    void change(int *x, int *y){x=y;}

    int main(){
    int *xx,*yy;

    yy = (int*)malloc(sizeof(int));
    change(xx,yy);

    if(xx == NULL)printf("is null\n");
    else printf("---- %d ----\n",*xx);

    .................................................. .........

    xx doesn't point to the value of yy (*yy) , the program prints "is null" . Why ?

    xx and yy must be declared int* , it's something that i must do in my program .
     
  2. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    A quick lesson on pointers. If a function has to change something that is passed in, then you need to pass in a pointer to that thing. For example,
    Code:
    void add1(int x)
    {
      x=x+1;
    }
    int main()
    {
      int var;
      add1(var);
    }
    
    won't increment var (although it will increment the local copy, which is held in x and discarded when the function returns), you need to do
    Code:
    void add1(int *x)
    {
      *x=*x+1;
    }
    int main()
    {
      int var;
      add1(&var);
    }
    
    instead. The & operator in this context takes the address of the variable it precedes; &var means "the address of var", and in add1() the * operator means the computer will treat the variable as a pointer and access memory at the location contained in the variable; suppose you have int foo; int *baz=&foo; then to access foo through the baz pointer you use *baz, and you can increment foo with *baz=*baz+1;. This is known a DEREFERENCING the pointer - a very important term.

    The same is true for pointers, if you need to modify a pointer, then you have to pass in the address of that pointer. So:
    Code:
    void incr_ptr(int *x) 
    {
      x=x+1;
    }
    int main()
    {
      int x[2];
      int *x_ptr=&x[0];
      incr_ptr(x_ptr);
    }
    
    won't increment x_ptr to point to x[1], although as before it WILL increase the local variable x, which is discarded when the function returns. If you want to increase x_ptr itself, then just as before you have to pass in a pointer and dereference it:
    Code:
    void incr_ptr(int **x) 
    {
      *x=*x+1;
    }
    int main()
    {
      int x[2];
      int *x_ptr=&x[0];
      incr_ptr(&x_ptr);
    }
    
    So your function change() only changes the local variable x, then discards that change. It leaves xx untouched. To modify xx you need to pass in a pointer to xx. xx itself is a pointer to int, so the x parameter to change() needs to be a pointer to a pointer to int. So:
    Code:
    void change(int **x,int *y)
    {
      *x = y;
    };
    int main()
    {
      int *xx, *yy;
      yy=malloc(sizeof int);
      change (&xx,yy);
      //etc
    
    should work. Note that y isn't declared as int** because you don't need to modify yy. This is a neat little example of using different levels of INDIRECTION (another important term - it's "indirect" because you don't go directly to the variable. int x would be direct. x is that number. int *ptr2x; is indirect; to get at x you have to go indirectly, via ptr2x, with *ptr2x).

    Despite the simplicity of the program there are still two bugs worth a mention:

    The value displayed by the program will be unpredictable, because *yy is uninitialised. Also, the program leaks memory, because the malloc() is not matched by a free(). Both these are major bugs; a memory leak in a long running program will mean that the program will eventually stop working because there's no memory left, and uninitialised variables will mean any behaviour dependent on the value of those variables will be unpredictable.

    So some good habits for you to develop immediately are:

    - ALWAYS initialise variables. Initialise them to zero if you can't think of a suitable value.
    - ALWAYS ALWAYS ALWAYS initialise pointers. Initialise them to zero.
    - ALWAYS write "free" somewhere, ideally in such a way as to cause a compiler error, when you write malloc(), because that will force you to deal with the free at the most important time (same is true for new/delete/new[]/delete[] in C++). Leaving it will mean that you forget it, which means (a) you'll get a leak and (b) you'll have to spend hours trying to find what is leaking. ALWAYS write resource allocation and resource deallocation simultaneously, or as simultaneously as possible.
    - Remember that allocating memory simply gives you somewhere to stuff a value. It doesn't do any value stuffing for you. int **yy=malloc(sizeof int); initialises yy to point to an int, but the int it points to is NOT DEFINED.
     
    jose_peeterson and shabbir like this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice