Pointers

Document Sample
Pointers Powered By Docstoc
					Pointers


      The best (and worst)
      thing about C
Best?

   Very Powerful
       Needed for any complex data structures
       Needed for dynamic memory
        management
   The “Sharpest” tool in your C toolkit.
       Makes a lot of things easier
       Faster, Smaller, etc…
Worst?

   If used incorrectly it can be bad.
       Hand + Power Drill = Hospital Visit
       Pointers + carelessness = Core Dump
   Segmentation faults are common
    when you misuse pointers.
   But, errors don’t always crash…
    sometimes they mess up
    your program later
What is a pointer anyway?
   It is a type… (int, float, pointer to int..)
   There is a pointer type for every type…
       A pointer to an int                 int *
       A pointer to a float                float *
   They can even point to other pointers!
       A pointer to a pointer to an int     int **
       A pointer to a pointer to a pointer to a pointer to
        an int                               int ****
       Etc.. (You usually see 1 star… occasionally 2…
        Almost never more than that though.)
Figure 9-12




         Declaring and Initializing




        Declare and
         initialize in
          one step
Figure 9-5




         Yeah, but what is a pointer?




                   int a = -123;
                   int *p = &a;
Yeah, but what is a pointer?
     It’s a variable that points to another.
      int val;     /* regular int       */
      int *ptr;    /* pointer to an int */




val     ptr


int     int *
Yeah, but what is it?
     It’s a variable that points to another.
      int val;     /* regular int       */
      int *ptr;    /* pointer to an int */
      ptr = &val; /* ptr contains the
                     address-of val */
                  /* ptr points to val */

val     ptr


int     int *
Yeah, but what is it?

     It’s a variable that points to another.
      *ptr = 42;   /* the target of ptr
                      becomes 42, whatever
                      that target may be…
                      indirection */

val     ptr
42
int     int *
Figure 9-7   int x, *p, *q;   p = &x;   q = &x;
Figure 9-7   int x, *p, *q;   p = &x;   q = &x;
Figure 9-7   int x, *p, *q;   p = &x;   q = &x;
Figure 9-7   int x, *p, *q;   p = &x;   q = &x;
Figure 9-21
And this is useful because…
   Bear with me for a moment…

   Let’s say we have a program which has two
    integers (int i, j;), and we want to be
    able to call a function to sort them such that
    i has the smaller, and j has the larger
    value…

   How do we swap values in a function
    without using pointers?
And this is useful because…
   Bear with me for a moment…

   Let’s say we have a program which has two
    integers (int i, j;), and we want to be
    able to call a function to sort them such that
    i has the smaller, and j has the larger
    value…

   How do we swap values in a function
    without using pointers?

             WE CAN’T!!!
   What about…

   int main() {
     int i=2, j=5;
     swap(&i, &j);
     return 0;
   }



main   i   j
       2   5
   What about…
   void swap(int *a, int *b);
   int main() {
     int i=2, j=5;
     swap(&i, &j); // Pass by reference
     return 0;
   }
swap   a   b   temp



main   i   j
       2   5
swaps

   By using pointers we can make ONE
    more generic swap routine:
       Using “Pass by reference” instead of
        “Pass by value”
void swap(int *a, int *b) {   // Swaps any two ints!
  int tmp;
  tmp = *a;
  *a = *b;
  *b = tmp;
}
   How do we use it?
   void swap(int *a, int *b) {
     int tmp;
     tmp = *a;
     *a = *b;
                       array1
     *b = tmp;
                       12 46 10        7   64 87   9   …
   }                    0 1 2          3   4 5     6

swap   a   b   tmp



main   i   j
                     swap( &i, &j );
       2   5
   How do we use it?
   void swap(int *a, int *b) {
     int tmp;
     tmp = *a;
     *a = *b;
     *b = tmp;
   }
swap   a   b   temp
               tmp
                2
               10

main   i   j
                      swap( &i, &j );
       2   5
   How do we use it?
   void swap(int *a, int *b) {
     int tmp;
     tmp = *a;
     *a = *b;
     *b = tmp;
   }
swap   a   b   temp
               tmp
                2
               10

main   i   j
                      swap( &i, &j );
       5
       2   5
   How do we use it?
   void swap(int *a, int *b) {
     int tmp;
     tmp = *a;
     *a = *b;
     *b = tmp;
   }
swap   a   b   tmp
               temp
                2
               10

main   i   j
                      swap( &i, &j );
       5
       2   2
           5
When do we need Pointers?
   When passing an array, it automatically
    passes by reference so anything we do in
    the function changes the original – no need
    to send the address for changing elements
    around

   What happens when we pass a struct to a
    function?
       Recall struct is passed by value – we get a copy
        of the struct
When do we need Pointers?
     What happens when we pass a struct to a function?
           Pass by value, get a duplicate
     Instead, pass a pointer to it

typedef struct
{
  int x, y;
} Pt;

void func( Pt *p );

int main( )
{
   Pt mypoint = { 1, 2 };
   printf( “BEFORE x = %d, y = %d\n”, mypoint.x, mypoint.y );
   func( &mypoint );
   printf( “BEFORE x = %d, y = %d\n”, mypoint.x, mypoint.y );
   return 0;
}

void func( Pt *p )
{
      (*p).x = 9;                             Must wrap
      (*p).y = 11;                           *p inside ( )
}
Nuthin’ much about NULL
    NULL

   NULL is a pointer to NOTHING!
    ptr = NULL; // NULL is a pointer to
                // address 0 (on most compilers)
   What is in *ptr?

    ptr


    int *
Some pointer secrets…

   pointer + int gives you a pointer
       It moves the pointer forward
           How much depends on the type of the pointer
   Example                 The thing ptr points to is 4 bytes…
                            So ptr + 1 will move you forward
    int array[5], *ptr;     4 bytes in memory.
    ptr = &array[2];
                            So, ptr + 2 will give you a pointer
    ptr = ptr + 2;          to the int two cells after ptr.
Some pointer secrets…

   pointer - int gives you a pointer
       It moves the pointer backward
   pointer - pointer gives you a int
       Gives you the difference between the
        memory cells
   pointer + pointer … not valid
   same with * / % etc…
Some pointer secrets…
   int i, a[100];
   An array IS a pointer!
       It points to the beginning of the cells
       All three of these are the same:
           a         &a             &a[0]


   a[i] is equivalent to *(a+i)
   what is the difference between a[i] and i[a]?
   Is 4[a] legal?
Arrays are pointers…
#include <stdio.h>
#include <stdlib.h>
void swap (int *a, int *b) {
  int temp;
  temp = *a;           void sort(int *arr, int len) {
  *a = *b;               int p,i;
  *b = temp;             for (p=1;p<len;p++)
}                          for (i=0;i<len-p;i++)
                             if (arr[i] > arr[i+1])
                               swap(&arr[i],&arr[i+1]);
                       }
int main() {
  int array1[100], array2[50], array3[500];
  ... // fill arrays
  sort(array1,100);
  sort(array2,50);
  sort(array3,500);
  ...
}
Arrays are pointers…
#include <stdio.h>
#include <stdlib.h>
void swap (int *a, int *b) {
  int temp;         void sort(int *arr, int len) {
  temp = *a;          int p,i;
  *a = *b;            for(p=1;p<len;p++)
  *b = temp;            for(i=0;i<len-p;i++)
}                         if(arr[i] > arr[i+1])
                             swap(&arr[i],&arr[i+1]);
                    }
                                 swap(arr+i,arr+i+1);
int main() {
  int array1[100], array2[50], array3[500];
  ... // fill arrays
  sort(array1,100);
  sort(array2,50);
  sort(array3,500);
  ...
}
Strings

   Strings are char arrays…

   But, arrays are just pointers…

   So a string is just a pointer to char(s)
String functions you may want
   strcpy(char *dest, char *src)
       copy a string from src to dest
   strcat(char *dest, char *src)
       copy src onto the end of dest
   strncpy(char *dest, char *src, int max)
       copy up to max chars from src to dest
   strncat(char *dest, char *src, int max)
       copy up to max chars from src onto the
        end of dest
String functions you may want

   strchr(char *s, char c)
       Returns a pointer to the first occurrence
        of the char c in the string s, or NULL if it
        isn’t there!
   strstr(char *haystack, char *needle)
       Returns a pointer to the first occurrence
        of the string needle in the string haystack,
        or NULL if it isn’t there!
String Funky Funk
   String Equality
   Consider:
    char *p = abc”, *q = “abc”;
    if ( p == q )
        printf( “Same address!\n” );
    else
        printf( “Different addresses\n” );

   What does it print?
       Depends on your compiler –
           String constants MAY be stored in the same location
            therefore optimized by pointing to the same spot
           But, some compilers will store them separately!
Returning Values
Returning values

   Pointers can also be used to return
    MULTIPLE values instead of just one
void   func(int *a, int *b, int *c) {
  *a   = 1;
  *b   = 4;
  *c   = 9;
}

int main() {
  int number, thingy, value;
  func(&number, &thingy, &value);
  func(&number, &number, &number);
  return 0;
}
Returning values

   How can you return TWO (or more)
    values from a function?

   Example: Write a function that takes
    two numbers and returns the quotient
    AND the remainder!
    Returning values

   Example: Write a function that takes two numbers
    and returns the quotient AND the remainder!


                     Dividend and
                      divisor are
                      input only


void long_division( int dividend, int divisor, int *quotientp, int *remainderp)
{
  *quotientp = dividend / divisor;
  *remainderp = dividend % divisor;
}
    Returning values

   Example: Write a function that takes two numbers
    and returns the quotient AND the remainder!

                                                    Values can be
                                                    Values can be
                                                      returned to
                                                      returned to
                                                    calling function
                                                    calling function
                                                    using pointers
                                                    using pointers

void long_division( int dividend, int divisor, int *quotientp, int *remainderp)
{
  *quotientp = dividend / divisor;
  *remainderp = dividend % divisor;
}
    Returning values
#include <stdio.h>

void long_division(int dividend, int divisor, int *quotientp, int *remainderp);

int main( )
{                                                     Send the
  int quot, rem;                                    address to the
                                                       function
    long_division(40, 3, &quot, &rem);
    printf("40 divided by 3 yields quotient %d ", quot);
    printf("and remainder %d\n", rem);
    return 0;
}
void long_division( int dividend, int divisor, int *quotientp, int *remainderp)
{
  *quotientp = dividend / divisor;
  *remainderp = dividend % divisor;
}
Ack! POW! Boom!
        PROBLEMS!
   Dereferencing a NULL pointer
       BOOM!

   Incorrectly applying address and indirection operators.
    Example: pt is a pointer
       pt = &45        // invalid – attempt to take address of a value
       pt = &(miles+10) // invalid – attempt to take address of a value
       pt = &miles + 10 // valid – 10 is added to address of miles

   Addresses of pointer constants cannot be taken
       Int nums[25];
        int *pt;
        pt = &nums; // invalid – nums is an address, so no address of the address!
        pt = nums;    // valid
PROBLEM! faults


   Don’t dereference a variable that is not a
    pointer!
    int num = 7;
    printf( “%d”, *num );

   Fastest way to a crash:
    *((int *) NULL) = 0;

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:1
posted:8/19/2012
language:
pages:45