Lecture – Advanced Pointers

Ryan Robucci

Table of Contents

References

Based from Advanced Pointers http://www.csee.umbc.edu/courses/undergraduate/313/spring12/Lectures/CPointersAdvanced.ppt

Don't Use Pointers Until Properly Initialized

Pointers to Pointers

  int age = 42;         
  int *pAge = &age;     
  int **ppAge = &pAge;     
• an int
• a pointer to an int
• a pointer to a pointer to an int

Exercise:

int main ( ) {

double gpa = 3.25, *pGpa, **ppGpa; 

pGpa = &gpa; 
ppGpa = &pGpa; 

printf( "%0.2f, %0.2f, %0.2f", gpa, *pGpa, **ppGpa); 
return 0; 
} 

 
 
• double, pointer to double, and
   pointer to a pointer to a double
• pgpa --> gpa
• ppGpa--> pGpa --> gpa
  
• Output? 
Result 3.25, 3.25, 3.25

Pointers to struct

typedef struct student {  
  char name[50];  
  char major [20]; 
  double gpa; 
} STUDENT_t; 

STUDENT_t bob = {"Bob Smith", "Math", 3.77}; 
STUDENT_t sally = {"Sally", "CSEE", 4.0}; 
STUDENT_t *pStudent;   
pStudent = &bob;                      

printf ("Bob's name: %s\n", pStudent->name); 
printf ("Bob's gpa : %f\n", pStudent->gpa); 

pStudent = &sally; 
printf ("Sally's name: %s\n", pStudent->name); 
printf ("Sally's gpa: %f\n", pStudent->gpa); 
• struct for student data
 
 
 
  
 
 
 
• "pointer to struct student"
  • pStudent --> bob
 
• use -> to access the members
• a->b result is same as (*a).b
  
• pStudent --> sally

Pointer in a struct

The data member of a struct can be any data type, including pointer. The struct person has a pointer to a struct name.

#define FNSIZE 50 
#define LNSIZE 40 

typedef struct name 
{
  char first[ FNSIZE + 1 ]; 
  char last [ LNSIZE + 1 ]; 
} NAME_t; 

typedef struct person {  
  NAME_t *pName;    
  int age; 
  double gpa; 
} PERSON_t;
 
 
 
 
  
 
 
 
 
 
• pointer to NAME struct 
 
 
  
  

Given the code below, how do we access bob's name, last name, and first name?
Draw a diagram of memory represented by these declarations

NAME bobsName = {"Bob", "Smith"}; 
PERSON bob; 
bob.age = 42; 
bob.gpa = 3.4; 
bob.pName = &bobsName;  

How might code access to the 3rd letter of Bob's first name?

Ans ```c ( (*(bob.pName)).first )[2] ((bob.pName)->first)[2] ```

Self-referencing struct

typedef struct player 
{ 
  char name[20]; 
  struct player *teammate;  
} TEAMMATE; 
TEAMMATE *team, bob, harry, john; 
team = &bob;
strncpy(bob.name, "bob", 20); 
bob.teammate = &harry;
strncpy(harry.name, "harry", 20); 
harry.teammate = &john; 
strncpy(john.name, "bill", 20); 
john.teammate = NULL: 
• tag "player"
 
 
• can't use TEAMMATE yet, use tag
 
 
• first player
 
• next teammate
 
• next teammate
 
• last teammate

Typical code to print a (linked) list, follow the teammate pointers until NULL is encountered:

 
TEAMMATE *t = team;

while (t != NULL) {
  printf("%s\n", t->name); // (*t).name 

  t = t->teammate;     //t=(*t).teammate; 
}
• start with the first player
• t=&bob
 
• while there are more players...
• print player name
 
• advance to next player 

Dynamic Memory

Dynamic Memory Functions

These functions are used to allocate and free dynamically allocated heap memory and are part of the standard C library.

void * and size_t

generic pointer

A generic pointer is a pointer of type void *.

null pointer

A null pointer is a pointer pointing to the address 0, or NULL.

Generic Pointers

Pointers of type (void *) can be useful to use one pointer variable to point to different data types at different times
(void *) is also the type returned by the dynamic memory allocation function malloc

Example:

void PrintGenericArray(void * ptr, char type, int numElements){ 
    char * c = (char *) ptr; 
    int * i= (int  *) ptr; 
    float * f= (float *) ptr; 
    int j=0; 
    switch (type) { 
        case 'c': for(;j<numElements; j++) printf("%c\n",*(c+j)); break; 
        case 'i': for(;j<numElements; j++) printf("%d\n",*(i+j)); break; 
        case 'f': for(;j<numElements; j++) printf("%f\n",*(f+j)); break; 
    } 
}

malloc for arrays

Exercise: rewrite this code using p as a pointer without using [ ]

calloc for arrays

realloc

Testing a returned pointer

assert

free

Dynamic Memory for structs

In C

typedef struct person{ 
    char name[ 51 ]; 
    int age; 
    double gpa; 
} PERSON; 
/* memory allocation */ 
PERSON *pbob = (PERSON *)malloc(sizeof(PERSON)); 
pbob->age = 42;             //same as (*pbob).age = 42; 
pbob->gpa = 3.5;            //same as (*pbob).gpa = 3.5; 
strcpy( pbob->name, “bob”); //same as strcpy((*pbob).name, “bob”); 
... 
/* explicitly freeing the memory */ 
free( pbob ); 

Java

In JAVA a garbage collector frees memory that no longer used/has a reference to it

public class Person         
{ 
  public int age; 
  public double gpa; 
} 
// memory allocation 
Person bob = new Person( );  
bob.age = 42; 
bob.gpa = 3.5; 
// bob is eventually freed by garbage collector 

Dynamic Teammates

typedef struct player{ 
  char name[20]; 
  struct player *teammate; 
} PLAYER; 

PLAYER *getPlayer( ){ 
  char *name = askUserForPlayerName( ); 
  PLAYER *p = (PLAYER *)malloc(sizeof(PLAYER)); 
  strncpy( p->name, name, 20 ); 
  p->teammate = NULL; 
  return p; 
}
int main ( ){ 
  int nrPlayers, count = 0; 
  PLAYER *pPlayer, *pTeam = NULL; 
  nrPlayers = askUserForNumberOfPlayers( ); 
  while (count < nrPlayers){ 
    pPlayer = getPlayer( ); 
    pPlayer->teammate = pTeam; 
    pTeam = pPlayer; 
    ++count; 
  }
   
  /* do other stuff with the PLAYERs */ 
  /* Exercise -- write code to free ALL the PLAYERs */ 
  return 0; 
}

Where does this code fail to check memory allocation?

Doubly-Linked (Non-Circular) Teammates

typedef struct player { 
  char name[20]; 
  struct player *nextteammate; 
  struct player *prevteammate; 
} TEAMMATE; 
TEAMMATE *team, bob, harry, john;
team = &bob;

strncpy(bob.name, "bob", 20); 
bob.prevteammate = NULL;       
bob.nextteammate = &harry;    

strncpy(harry.name, "harry", 20);
harry.prevteammate = &bob;    
harry.nextteammate = &john;    

strncpy(john.name, "john", 20);
john.prevteammate = &harry:
john.nextteammate = NULL;    
 
 •head is first player
 •create first player
    ‣write name
    ‣NULL prev teammate
    ‣next teammate
 •create second player
    ‣write name
    ‣prev teammate
    ‣next teammate
 •third second player
    ‣write name
    ‣prev teammate
    ‣NULL next teammate

Doubly-, Circularly-Linked Teammates

typedef struct player { 
  char name[20]; 
  struct player *nextteammate; 
  struct player *prevteammate; 
} TEAMMATE; 
TEAMMATE *team, bob, harry, john; 
team = &bob;                       
strncpy(bob.name, "bob", 20); 
bob.prevteammate = &john           
bob.nextteammate = &harry;         
strncpy(harry.name, "harry", 20);
harry.prevteammate = &bob;
harry.nextteammate = &john; 
strncpy(john.name, "john", 20);
john.prevteammate = &harry:
john.nextteammate = &bob;
 
 
 
• head --> tail
 
 
 
 
• tail --> head
 

Returning Dynamic Arrays Using Pointers

    char *getCharArray( int size ){ 
      char *cp = (char *)malloc( size * sizeof(char)); 
      assert( cp != NULL); 

      return cp; 
    }
 
•on the heap
•allocation check with  
    minimal handling
•return pointer to allocated memory

Dynamic Multi-Dimensional Arrays

Linked List Insert and Delete

http://www.csee.umbc.edu/courses/undergraduate/201/fall08/lectures/index.shtml
http://www.csee.umbc.edu/courses/undergraduate/201/fall08/lectures/linkedlist/

Cover Implementation: insert and delete