A brief review on operators:
|
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 &:
|
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 !!!
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++)
|
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[]) { } |
|
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 } |
|
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 } |
|
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);
}
|
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 !
|
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 *:
|
Important note:
|
Before I show you an example of the * operator, you need to know that:
|
The precedence of the operators will help you understand how the expression is evaluated.
int *p, a, b; // p stores address of int typed variables
|
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
|
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
|
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
|
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
|
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);
}
|
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
|
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 );
}
|