CSCI 255 Pointers

Areas of memory

Often running C programs are considered to have several segments or sections, distinct areas of memory.

Some compilers/architectures may place const variables in read-only segments. In many compilers/architectures each shared or dynamic-link library has its own segments for text and data. This allows several running programs to share common library routines.

Example C program using all areas

uint32_t Aglobal[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
const uint32_t Aconst[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
uint32_t Abss[10] ;

void subr(void) {
  uint32_t ASlocal[10] ;
  return ;
}

int main(int argc, char** argv) {
  uint32_t AMlocal[10] ;
  uint32_t *Amalloc ;
  Amalloc = (uint32_t *)malloc(10*sizeof(uint32_t)) ;
  subr() ;
  return (EXIT_SUCCESS);
}

Some address for those variables

Variable64-bit linux16-bit PIC
Aglobal0000000000600B000850
Aconst00000000004007A09072
Abss0000000000600B600878
Amalloc000000000089701009AE
AMlocal00007FFF09C89C8009F2
ASlocal00007FFF09C89C300A24
main00000000004005411204
subr000000000040051411EA
printf00000000004003F80459

Pointers

Examples of functions using pointers

void swap(int *p, int *q) {
  int t = *p ;
  *p = *q ;
  *q = t ;
}
void sort(int *mn, int *mx) {
  if (*mn > *mx) {
    swap(&mn, &mx) ;
  }
}
char *firstLetter(char *msg) {
  while (*msg && !isalpha(*msg)) {
    ++msg ;
  }
  return msg ;
}
char *firstLetter(char *msg) {
  while (*msg && !isalpha(*msg++)) ;
  return msg ;
}

Examples of implementing pointers on the PIC

       MOV     x,W2            ;; W2 <- x
       MOV     #x,W3           ;; W3 <- &x
       MOV     [W3],W2         ;; W2 <- *W3
       MOV     W5,[W3]         ;; *W5 <- W5
       MOV     [W6],[W7]       ;; *W7 <- *W6
       MOV     [W8++],[++W9]   ;; *++W9 <- *W8++

Arrays and pointers in C

In C, an array declaration defines a constant pointer to a sequence of data values. For example:
        int A[] = {2, 3, 5} ;
is really the same type as:
        int * const A = {2, 3, 5} ;

Incidently, this is not the same as:
        const int A[] = {2, 3, 5} ;
or
        const int * A = {2, 3, 5} ;

Finally, all you Java programmers should be warned that the following, while encouraged in Java, is forbidden in C:
        int[] A = {2, 3, 5} ;

Pointer arithmetic in C

If p is the address of an integer in C, then p+i is the address of the i’th integer stored in memory after the place p points to. This interpretation means that p[i] can be considered an abbrevation for *(p+i).

Two equivalent C loops

for (i=0; i<1000; ++i) {
  A[i] = B[i] ;
}
int *pA = &A[0]  ;
int *pB = &B[0]  ;
for (i=0; i<1000; ++i) {
  *pA++ = *pB++ ;
}

Examples of implementing arrays on the PIC

Assume that c is an array of 8-bit characters. Each character will require one byte.

       MOV.B   W2,x+5          ;; c[5] <- W2
       MOV.B   x+5,W2          ;; W2 <- c[5]
       MOV.B   W2,[W4+5]       ;; W4[5] <- W2
       MOV.B   [W4+5],W2       ;; W2 <- W4[5]
       MOV.B   [W4+W5],W2      ;; W2 <- W4[W5]

Now, assume that x is an array of 16-bit integers. Each integer will require two bytes.

       MOV     W2,x+10         ;; x[5] <- W2
       MOV     x+10,W2         ;; W2 <- x[5]
       MOV     W2,[W4+10]      ;; W4[5] <- W2
       MOV     [W4+10],W2      ;; W2 <- W4[5]
       ADD     W5,W5,W0        ;;
       MOV     [W4+W0],W2      ;; W2 <- W4[W5]

Getting the right address

The following two lines of PIC code will increase the value stored in W7 by one and the value stored in W8 by two.

       MOV.B   [++W7],W0
       MOV     [++W8],W0

Faster loops

The PIC instruction set has a REPEAT instruction that is designed to make loops a bit more succinct. Here is an implementation of the C for shown above that copied the first 1000 elements of B into A.

       MOV     #A,W5
       MOV     #B,W6
       REPEAT  #999
       MOV     [W6++],[W5++]

A brief look at structure

C has a non-heterogenous data structure called the struct, resembling a method-less class in Java, where several fields are stored within a collection.

struct point3D {
  int x ;
  int y ;
  int z ;
}
struct point3D P ;
P.x = 5 ;
P.y = P.x + 1 ;
P.z = 7 ;

When implemented the fields are stored at fixed offsets from the beginning of the structure.

       MOV     P+2,W5          ;; W5 <- P.y 
       MOV     W5,P+4          ;; P.z <- W5

Trying out an example

int V[500] ;
int H[100] ;
int i ;
for (i=0; i<100; ++i) {
  H[i] = 0 ;
}
for (i=0; i<500; ++i) {
  ++H[V[i]] ;
}