# Pointers Memory Arrangement u Memory is arranged in

• Slides: 43

Pointers .

Memory Arrangement u. Memory is arranged in a sequence of addressable units (usually bytes) · sizeof( <Type> ) return the number of units it takes to store a type. · sizeof(char) = 1 · sizeof(int) = 4 (on most of our machines) · Try calling sizeof on other types!

Memory int main() { char c; int i, j; double x; … c i j x

Arrays Defines a block of consecutive cells int main() { int i; int a[4]; … i a[0] a[1] a[2] a[3]

Arrays - the [ ] operator int arr[5] = {1, 5, 2, 1 , 3}; /*arr begins at address 40*/ 1 40 u 5 44 2 48 1 52 3 56 60 Address Computation Examples arr[0] 40+0*sizeof(int) = 40 arr[3] 40+3*sizeof(int) = 52 arr[i] 40+i*sizeof(int) = 40 + 4*i arr[-1] 40+(-1)*sizeof (int) = 36 // can be the code segment or other variables. That is BAD

Arrays u. C does not provide any run time checks int a[4]; a[-1] = 0; a[4] = 0; This will compile and run (no errors) …but can lead to unpredictable results. u. It is the programmer’s responsibility to check whether the index is out of bounds…

? איך כותבים את זה בסי - סינטקס u. Declaration <type>* p; p points to objects of type <type> u. Pointer value *p = x; y = *p; *p refers to the object p points to uvalue pointer &x - the address of x

1 דוגמא int main() { int i, j; int *x; // x points to an integer i = 1; x = &i; j = *x; x = &j; (*x) = 3; i j x 1

1 דוגמא int main() { int i, j; int* x; i = 1; x = &i; // x takes the adress of i j = *x; x = &j; (*x) = 3; i j 1 0 x 0100 x 0 x 0100

1 דוגמא int main() { int i, j; int *x; i = 1; x = &i; j = *x; // j takes the value stored // at the address x holds x = &j; (*x) = 3; i j 1 0 x 0100 x 1 0 x 0100

1 דוגמא int main() { int i, j; int *x; i = 1; x = &i; j = *x; x = &j; // x takes the address of j (*x) = 3; i j 1 0 x 0100 x 1 0 x 0104

1 דוגמא int main() { int i, j; int *x; i = 1; x = &i; j = *x; x = &j; (*x) = 3; // go to the address stored at // x, and put there 3 i j 1 0 x 0100 x 3 0 x 0104

Example 2 – the swap function Does nothing void swap(int a, int b) { int temp = a; a = b; b = temp; } …. int main() { int x, y; x = 3; y = 7; swap(x, y); // now x==3, y==7 …. Works void swap(int *pa, int *pb) { int temp = *pa; *pa = *pb; *pb = temp; } …. int main() { int x, y; x = 3; y = 7; swap(&x, &y); // x == 7, y == 3 …

יחסיות לגודל הטיפוס . חשבון מצביעים מתבצע ביחס לגודל של הטיפוס המוצבע : ז " א u ptr + n Will move ptr, (n * sizeof(*ptr)) places in memory. u ptr 1 – ptr 2 is equal to the adress in ptr 1, substracted the address in ptr 2, and devided by sizeof(*ptr 1) Reminder: ptr 1 and ptr 2 must point to the same type

דוגמא - חיבור שלם למצביע int a[4]; int *p = a; char *q = (char *)a; // Explicit cast // p and q point to the same location p = p+2; // increment p by 2 int (4 bytes) q = q+2; // increment q by 1 char (1 byte) a[0] q a[1] a[2] p a[3]

דוגמא - חיסור מצביעים int Find. First. Non. Zero( int a[], int n ) { int *p; for( p = a; p < a+n && (*p) == 0; p++ ) ; return p-a; } Same as int Find. First. Non. Zero( int a[], int n ) { int i; for( i = 0; i < n && a[i] == 0; i++ ) ; return i; }

Pointers & Arrays Addressing in arrays is actually pointers arithmethic! int *p; int a[4]; p = &a[0]; *(p+1) = 1; // assignment to a[1]! p a[0] a[1] a[2] a[3]

Pointers & Arrays are essentially constant pointers! int *p; int a[4]; p = a; // same as p = &a[0] p[1] = 102; // same as *(p+1)=102; *(a+1) = 102; // same p++; // p == a+1 == &a[1] a = p; // illegal. a is constant a++; // illegal. a is constant

Pointers & Arrays int foo( int *p ); and int foo( int a[] ); Are declaring the same interface u. In both cases, a pointer to int is being passed to the function foo

NULL Pointer

NULL pointer u. Special value: uninitialized pointer int *p = NULL; … if( p != NULL ) { … }

NULL pointer int *p = NULL; *p = 1; Will compile… … but will lead to runtime error Which is much better then just dealing with a random garbage address, without being aware of it!

Arrays u. C does not provide array operations int … a = if( … a[4]; b; // illegal a == b ) // illegal

Array Initialization int int arr[3] arr[4] arr[2] = = {3, {3, 4, 4, 5}; 5}; // // Good - The same Good - The last is 0 Bad int arr[2][3] = {{2, 5, 7}, {4, 6, 7}}; // Good int arr[2][3] = {2, 5, 7, 4, 6, 7}; // Good - The same int arr[3][2] = {{2, 5, 7}, {4, 6, 7}}; // Bad int arr[3]; arr = {2, 5, 7}; // Bad - array assignment only in initialization