Lecture – C Pointer Variables

Ryan Robucci

Table of Contents

Opening Discussion on Use of Pointers

Consider a scenario in main where some data has been captured, but it must be converted from signed-6 bit to signed 8-bit

assembly code loop:

byte dataHigh [500]; 
byte dataLow [500]; 
... 
for(i=0;i<500;i++) {
    dataLow [i]=PINA;
    dataHigh [i]=PINB;
    delay_ms(1);
}

Use of pointers:

One way is to store the 500 data points in a contiguous block of memory. Then, the only information need is

Information required to use a contiguous data blob representing an array:

  1. the address of the first element and
  2. the number of bytes (or bits) to advance in memory to find the next element
    • and know how to advance by this increment in the given archetecture/platform
  3. agreed upon interpretation of the bits of element

Arrays are set up this way in C. In C, a simple data array is stored in contiguous block of memory (so far as the program can tell since any memory paging is abstracted).

  1. The location of the array is tracked using the address of the first element, which is stored in the array variable itself.
  2. The type of the elements (int, char, float, etc…) defines the number of bytes to move forward by to find subsequent elements as well as the interpretation

So, if you know data[0] exist at memory location 0x0F10, where is the second point?

So, how is the size of the base data type known by the function?

So if you know where the first point of data is in an array, you know where the second point is (address of first point + size of datatype) on so on for the rest of the array

What about the length of the array?

Length of Array

Remember, the end of the array must always be encoded via some mechanism or convention:

Other reaons to use pointers:

So, we’ve discussed one reason to use pointers: sharing large sets of data with functions without unnecessary copying
(we discussed arrays, later we will discuss other large data structures like structs, lists, trees etc…)

Later we will use pointers to keep track of and refer to dynamically allocated (run-time) arrays and structures as opposed to arrays and variables that are defined at compile time and can have there location known at compile-time.

Syntax of pointers in C

Now we need some syntax in C to provide away to code all of this. Lets look at some function prototypes and what parameters are pushed on the stack (assuming parameters passed on the stack)

The alternative syntax for the second is

New Types for Variable: Pointer

So, we have a new variable type (int *).

Example:

int count;   
int * ptrCount; 

We can “point to”/reference/“store address of” count like this:
ampersand prefix means return a pointer to, or “address of”

ptrCount  = & count; 

We can use ptrCount as a regular int variable through dereferencing.
* is the dereference operator

(*ptrCount) = (*ptrCount) + 1; // modifies count 

Pointer variables can be used used to modify other variables

A pointer variable can be used to modify other variables. It can also be passed to functions to do the same.

Here is an example:

void SameMax( int * ptrA, int * ptrB){ 
  if (*ptrA  >  *ptrB){ 
    *ptrB = *ptrA; 
  } else {  
    *ptrA = *ptrB; 
} 

…somewhere in main…

int a = 1, b=2; 
int * ptrInt; 

ptrInt = & a; 

Now we can pass the pointer

SameMax(ptrInt, &b); 

or

SameMax(&a, &b); 

Both result in a=2, b=2. (&a creates a pointer)

What is a pointers

Why pointers?

Caution with Pointers

Java Reference vs. C Pointers (reference slide, not covered)

In Java, a reference variable is used to give a name to an object. The reference variable contains the memory address at which the object is stored.

Truck ford = new Truck( );

Since C does not support objects, it does not provide reference variables. However, C provides pointer variables which contain the memory address of another variable (sometimes called the “pointee”). A pointer may point to any kind of variable.

C Pointer Variables

To declare a pointer variable, we must do two things

Pointer Declaration

Pointer Operators

Pointer Examples

int x = 1, y = 2, z[10];

int *ip;        /* ip is a pointer to an int */

ip = &x;        /* ip points to (stores the memory address of) x */

y = *ip;        /* y is now 1, indirectly copied from x using ip */

*ip = 0;        /* x is now 0 */ 

ip = &z[5];    /* ip now points to z[5] */ 

When in doubt about order of operations, or to increase readability and conveyance of intent, use parenthesis

If ip points to x, then *ip can be used anywhere x can be used so for the above example, the following are equivalent:

The unary operators (one operand) * and & are higher precedence than binary arithmetic operators (two operands). So y = *ip + 1; takes the value of the variable to which ip points, adds 1 and assigns it to y

The statements *ip += 1; and ++*ip; and (*ip)++; each increment the variable to which ip points.

Pointer and Variable types (Objective Type)

More Pointer Code

NULL

Pointers and Function Arguments

Incorrect Swap

A corrected swap( )

More Pointer Function Parameters

ConvertTime.c

void ConvertTime (int time, int *pHours, int *pMins)  
{ 
  *pHours = time / 60; 
  *pMins = time % 60; 
}  
int main( ) 
{ 
  int time, hours, minutes; 
  printf("Enter a time duration in minutes: "); 
  scanf ("%d", &time); 
  ConvertTime (time, &hours, &minutes); 
  printf("HH:MM format: %d:%02d\n", hours, minutes); 
  return 0; 
}

An Exercise

Answer 4, 4 

3, 7

Pointers -> struct (for reference, will cover this slide content later)

We still have one more syntax for pointers to learn ->, but we this will be covered after struct and union are covered

/* define a struct for related student data */ 
typedef struct student {  
    char name[50];  
    char major [20]; 
    double gpa; 
} STUDENT; 

STUDENT bob = {"Bob Smith", "Math", 3.77}; 
STUDENT sally = {"Sally", "CSEE", 4.0}; 
STUDENT *pStudent;         /* pStudent is a "pointer to struct student" */  

/* make pStudent point to bob */ 
pStudent = &bob;  
/* use -> to access the members */  
printf ("Bob's name: %s\n", pStudent->name); 
printf ("Bob's gpa : %f\n", pStudent->gpa); 
/* make pStudent point to sally */ 
pStudent = &sally; 
printf ("Sally's name: %s\n", pStudent->name); 
printf ("Sally's gpa: %f\n", pStudent->gpa); 
Note too that the following are equivalent. Why??  
pStudent->gpa and (*pStudent).gpa         /* the parentheses are necessary */
void PrintStudent(STUDENT *studentp) 
{ 
    printf("Name : %s\n", studentp->name); 
    printf("Major: %s\n", studentp->major); 
    printf("GPA  : %4.2f", studentp->gpa); 
} 

Passing a pointer to a struct to a function is more efficient than passing the struct itself.  Why is this true?