Review: operators

A brief review on operators:

  1. An operator operates on one or more operands (values)

  2. An operator returns some result based on its operands

  3. The returned result has a specific data type and the return data type can be different from the operand type(s) !!!

Example:

  The integer addition operator  +:

    (1) +  operates on  2 int operands  (binary operator) 
    (2) +  returns the sum of its operands
    (3) +  returns a result of the type int

     3 + 4 = 7  (result) 

The reference operator & of C

The reference operator &:

  1. The reference operator & operates on one variable of any data type
    (I.e. & is a unary operator)

  2. The reference operator & returns the (base) address of the variable

  3. The data type of the result is the reference type of the data type of the variable

Example:

 int a;
 float b;
 
 &a   returns the address of the int   typed variable a
 &b   returns the address of the float typed variable b

Note: the data type of &a and &b are different !!!

The reference operator & of C - Examples
 

In C, the programmer can use the & operator to find the address of any variable in the program:

  #include <stdio.h>

  int    i = 4;
  short  s = 5;
  float  f = 6.0;
  double d = 7.0;

  int main(int argc, char *argv[])
  {
     printf("Address of i = %p\n", &i );  // %p = pointer 
     printf("Address of s = %p\n", &s );
     printf("Address of f = %p\n", &f );
     printf("Address of d = %p\n", &d );
  } 

This feature is not available in any other programming language (except C++)

What can you do with the result of &var ?

  • Recall one of the features that a data type provides is:

      • The program can define (= create) variables of the data type to store values of the data type

Example: storing addresses into reference typed variables

 #include <stdio.h>
 int    i = 4, *p; // p stores addresses of int   typed vars
 short  s = 5, *q; // q stores addresses of short typed vars

 int main(int argc, char *argv[])
 {




 } 

What can you do with the result of &var ?

  • Recall one of the features that a data type provides is:

      • The program can define (= create) variables of the data type to store values of the data type

Example: storing addresses into reference typed variables

 #include <stdio.h>
 int    i = 4, *p; // p stores addresses of int   typed vars
 short  s = 5, *q; // q stores addresses of short typed vars

 int main(int argc, char *argv[])
 {
        &i; // this is the address of an  int typed var
        &s; // this is the address of a short typed var 


 } 

What can you do with the result of &var ?

  • Recall one of the features that a data type provides is:

      • The program can define (= create) variables of the data type to store values of the data type

Example: storing addresses into reference typed variables

 #include <stdio.h>
 int    i = 4, *p; // p stores addresses of int   typed vars
 short  s = 5, *q; // q stores addresses of short typed vars

 int main(int argc, char *argv[])
 {
    p = &i; // stores the address of var i in p
    q = &s; // stores the address of var s in q 


 } 

What can you do with the result of &var ?

  • Recall one of the features that a data type provides is:

      • The program can define (= create) variables of the data type to store values of the data type

Example: DEMO

 #include <stdio.h>
 int    i = 4, *p;
 short  s = 5, *q;

 int main(int argc, char *argv[])
 {
    p = &i; 
    q = &s; 
    printf("address of i = %p\n", p);
    printf("address of s = %p\n", q);
 } 

Using assembler to illustrate the & operator
 

This is how the C compiler translates p = &i:

  C:                   ARM assembler
  ==================   ============================
  int    i, *p;        .data
                       i: .skip 4  
                       p: .skip 4 // an address is 4 bytes 

  p = &i;	       .text
                       movw r0, #:lower16:i
                       movt r0, #:upper16:i // r0 = &i 
		       movw r1, #:lower16:p
		       movt r1, #:upper16:p
		       str  r0, [r1]        // p = &i
   

The mechanism to find the address of any variable is a powerful feature - it's only available in assembler programming languages !

Note: you cannot find out the address of a variable in Java !

Important note: data types returned by the & operator

  • Recall this very important fact:

      • There are many different reference data types         

  • The different reference data types are conflicting types

These assignments are illegal due to type conflicts:

 int    i = 4, *p; // p must store an addr of an int typed var
 short  s = 5, *q; // q must store an addr of an short var

 int main(int argc, char *argv[])
 {
    p = &s; // Illegal: stores addr of a short type var in p
    q = &i; // Illegal: stores addr of a int type var in q
 } 

The de-reference operator * of C

The de-reference operator *:

  1. The de-reference operator * operates on a reference variable
    (I.e. * is a unary operator)

  2. The de-reference operator * returns the variable at address given in the reference variable

  3. The data type of the result is the data type of the referred variable

Important note:

  • The * operator is very unusual in that the return result is a variable

  • Result:   the * operator is one of few operators that can be used on the left hand size of the assignment statement !!!

The precendence of the & operator and the * operator -- click here
 

Before I show you an example of the * operator, you need to know that:

  • The & operator and the * operator has the 2nd highest precendence among all the C operators

  • A table with the operator precedence is at this webpage: click here

  • For programming convenience, you should remember that:

      • The & operation and the * operation are performed before all arithmetic (+. -, *, /, %), logic (&&, ||, !) and assignment (=, +=, -=, ....) operations

The precedence of the operators will help you understand how the expression is evaluated.

Examples of the de-reference operator * of C
 

  int *p, a, b;  // p stores address of int typed variables  

 

   
      

  

  

  

    
            

  

    
   

Examples of the de-reference operator * of C
 

  int *p, a, b;  // p stores address of int typed variables  

  After this assignment:

     p = &a; // p will store the address of 
             // the int type variable a



 

 

   
           

 

   
   

Examples of the de-reference operator * of C
 

  int *p, a, b;  // p stores address of int typed variables  

  After this assignment:

     p = &a; // p will store the address of 
             // the int type variable a

  Then the expression:

     *p      // is equivalent to a anywhere in the program

 

   
           

 

   
   

Examples of the de-reference operator * of C
 

  int *p, a, b;  // p stores address of int typed variables  

  After this assignment:

     p = &a; // p will store the address of 
             // the int type variable a

  Then the expression:

     *p      // is equivalent to a anywhere in the program

  And after this assignment:

     p = &b; // p will store the address of 
             // the int type variable b



 
   

Examples of the de-reference operator * of C
 

  int *p, a, b;  // p stores address of int typed variables  

  After this assignment:

     p = &a; // p will store the address of 
             // the int type variable a

  Then the expression:

     *p      // is equivalent to a anywhere in the program

  And after this assignment:

     p = &b; // p will store the address of 
             // the int type variable b

  Now the expression:

     *p      // is equivalent to b anywhere in the program
   

Using reference variables as alias for variables

Reference variables in C are often used as aliases (= another name) for variables.

Example:

#include <stdio.h>

int main(int argc, char *argv[])
{ 
    int a = 4, b = 8, *p;
  
    p = &a;          // Now *p is an alias for a
    *p = *p + 100;   // ≡ a = a + 100

    printf("a = %d, b = %d\n", a, b);

    p = &b;          // Now *p is an alias for b
    *p = *p + 200;   // ≡ b = b + 200

    printf("a = %d, b = %d\n", a, b);
}    

What is happening behind the scene ? Revealed with ARM assembler code

This is how the C compiler translates *p = *p + 99:

 // *p = *p + 99
 movw    r0, #:lower16:p
 movw    r0, #:upper16:p 
 ldr     r0, [r0]     // r0 = p (= addr of some int typed var)
 ldr	 r0, [r0]     // Use addr to load value from variable

 // *p = *p + 99
 add     r1, r0, #99      // r1 = RHS

 // *p = *p + 99
 movw    r0, #:lower16:p
 movw    r0, #:upper16:p 
 ldr     r0, [r0]         // r0 = p
 str     r1, [r0]         // Use p to write value to variable
   

So when p contains the address of variable a , *p = *p + 99 will add 99 to the a

And when p contains the address of variable b , *p = *p + 99 will add 99 to the b

Pointer variables
 

  • A reference typed variable is also known as a pointer variable

    Reason: a reference typed variable points to another variable:

Relationship between the & and * operators

The * operator is the inverse operator for the & operator

 This is valid for any variable x:

      *(&x)x  // Their data types are same too ! 

Example:

#include <stdio.h>

int main(int argc, char *argv[])
{
    int i;

    i = 4;
    printf("i = %d\n", i );

    *(&i) = 9999; // Equiv to: i = 9999;     
    printf("i = %d\n", i ); 
}