810 likes | 992 Vues
C Program Design C Pointers. 主講人:虞台文. Content. Introduction Point Operators Calling Functions by References Pointer Expressions and Pointer Arithmetic Pointers and Arrays Using the const Qualifier with Pointers Arrays of Pointers. C Program Design C Pointers. Introduction.
E N D
C Program DesignC Pointers 主講人:虞台文
Content • Introduction • Point Operators • Calling Functions by References • Pointer Expressions and Pointer Arithmetic • Pointers and Arrays • Using the const Qualifier with Pointers • Arrays of Pointers
C Program DesignC Pointers Introduction
00000000 00000001 00000002 00000003 00000004 00000005 00000006 00000007 00000008 FFFFFFFB FFFFFFFC FFFFFFFD FFFFFFFE FFFFFFFF Memory Space • Program and data are stored in some places of memory. • Addresses (Pointers) are used to identify where the program or data are stored. • CPU accesses a piece of memory data by emitting its address on address bus. address
C Pointers • Powerful, but difficult to master • Simulatecall-by-reference • C only has call-by-value • Close relationship with arrays and strings • important for handling arrays and strings
C Program DesignC Pointers Pointer Variable Definitions and Initialization
Variable is a piece of memory containing a value of a specific type (direct reference). Pointer Variables • Pointer variables contain memory addresses as their values • Indirect reference • Typed pointers point to the address of a variable of a specific type • Non-typed pointers are simply addresses, i.e., they can point to an addresses of any thing
Pointer Definitions datatype *pointerName Examples: int *ptr1; int *ptr2, *ptr3; char *ptr4; double *ptr5; void *ptr6, *ptr7; Typed pointers Non-typed pointers
Pointer Definitions datatype *pointerName Don’t write as int *ptr2, ptr3; Examples: int *ptr1; int *ptr2, *ptr3; char *ptr4; double *ptr5; void *ptr6, *ptr7; Typed pointers Non-typed pointers
ptr1 ptr2 ptr3 ptr4 ptr5 ptr6 ptr7 Pointer Initialization Where these pointers point to? int *ptr1; int *ptr2, *ptr3; char *ptr4; double *ptr5; void *ptr6, *ptr7;
ptr1 ptr2 ptr3 ptr4 ptr5 ptr6 ptr7 Before pointers are actually used, it is a good habit to initialize them to NULL, meaning that they are pointing to nothing. Pointer Initialization #define NULL 0 int *ptr1=NULL; int *ptr2=NULL, *ptr3=NULL; char *ptr4=NULL; double *ptr5=NULL; void *ptr6=NULL, *ptr7=NULL;
C Program DesignC Pointers Pointer Operators
Point Operators • Reference operator (&) • Retrieve the address of a variable • Dereference operator (*) • Retrieve the value pointed by a pointer (address) • * and & are inverses • They cancel each other out
5 3.14 Nickname: address-of operator Reference Operator (*) • &: Returns address-of operand int n=5; double x=3.14; . . . . . int *nPtr; double *xPtr; nPtr = &n; xPtr = &x; n x . . . nPtr xPtr
n 5 3.14 x . . . nPtr xPtr 範例: #include <stdio.h> int n=5; double x=3.14; int *nPtr; double *xPtr; main() { /* nPtr gets address of n */ nPtr = &n; /* xPtr gets address of n */ xPtr = &x; printf("Address of n is %p\n" "Address of x is %p\n", nPtr, xPtr); } 00427600 00427608 00427600 00427608
n 5 3.14 x . . . nPtr xPtr 練習: #include <stdio.h> int n=5; double x=3.14; int *nPtr; double *xPtr; main() { /* nPtr gets address of n */ nPtr = &n; /* xPtr gets address of n */ xPtr = &x; printf("Address of n is %p\n" "Address of x is %p\n", nPtr, xPtr); } • 將上例之變數改成main之區域變數,觀察其值,並繪製類似右側之圖。 00427600 00427608 00427600 00427608
n 5 3.14 x . . . nPtr xPtr Nickname: value-point-by operator Dereference Operator (*) • *: Returns value point by operand 00427600 *nPtr = ? *xPtr = ? 00427608 00427600 00427608
n 5 3.14 x . . . nPtr xPtr Nickname: value-point-by operator Dereference Operator (*) • *: Returns value point by operand #include <stdio.h> int n=5; double x=3.14; int *nPtr; double *xPtr; main() { /* nPtr gets address of n */ nPtr = &n; /* xPtr gets address of n */ xPtr = &x; printf("integer value in address %p is %d\n" "double value in address %p is %lf\n", nPtr, *nPtr, xPtr, *xPtr); } 00427600 *nPtr = ? *xPtr = ? 00427608 00427600 00427608
範例: Showing that * and & are complements of each other. #include <stdio.h> int main( void ) { int a; /* a is an integer */ int *aPtr; /* aPtr is a pointer to an integer */ a = 7; aPtr = &a; /* aPtr set to address of a */ printf( "The address of a is %p" "\nThe value of aPtr is %p", &a, aPtr ); printf( "\n\nThe value of a is %d" "\nThe value of *aPtr is %d", a, *aPtr ); printf( "\n\nShowing that * and & are complements of " "each other\n&*aPtr = %p" "\n*&aPtr = %p\n", &*aPtr, *&aPtr ); return 0; /* indicates successful termination */ } /* end main */
0012FF7C a 7 aPtr 0012FF7C 範例: Showing that * and & are complements of each other. #include <stdio.h> int main( void ) { int a; /* a is an integer */ int *aPtr; /* aPtr is a pointer to an integer */ a = 7; aPtr = &a; /* aPtr set to address of a */ printf( "The address of a is %p" "\nThe value of aPtr is %p", &a, aPtr ); printf( "\n\nThe value of a is %d" "\nThe value of *aPtr is %d", a, *aPtr ); printf( "\n\nShowing that * and & are complements of " "each other\n&*aPtr = %p" "\n*&aPtr = %p\n", &*aPtr, *&aPtr ); return 0; /* indicates successful termination */ } /* end main */
0012FF7C a 7 aPtr 0012FF7C • What is the data type of &aPtr? • Modify the following program to also show the address of aPtr. 練習: #include <stdio.h> int main( void ) { int a; /* a is an integer */ int *aPtr; /* aPtr is a pointer to an integer */ a = 7; aPtr = &a; /* aPtr set to address of a */ printf( "The address of a is %p" "\nThe value of aPtr is %p", &a, aPtr ); printf( "\n\nThe value of a is %d" "\nThe value of *aPtr is %d", a, *aPtr ); printf( "\n\nShowing that * and & are complements of " "each other\n&*aPtr = %p" "\n*&aPtr = %p\n", &*aPtr, *&aPtr ); return 0; /* indicates successful termination */ } /* end main */
C Program DesignC Pointers Calling Functions by Reference
C Simple Swap Program #include <stdio.h> main() { int a = 23, b = 47; int t; printf("Before. a: %d, b: %d\n", a, b); t = a; a = b; b = t; printf("After. a: %d, b: %d\n", a, b); }
C Simple Swap Program #include <stdio.h> main() { int a = 23, b = 47; int t; printf("Before. a: %d, b: %d\n", a, b); t = a; a = b; b = t; printf("After. a: %d, b: %d\n", a, b); } define a function to do swapping.
void swap(int a, int b) { int t; t = a; a = b; b = t; } C Simple Swap Program #include <stdio.h> main() { int a = 23, b = 47; printf("Before. a: %d, b: %d\n", a, b); swap(a, b); printf("After. a: %d, b: %d\n", a, b); } Workable?
void swap(int a, int b) { int t; t = a; a = b; b = t; } C Simple Swap Program #include <stdio.h> main() { int a = 23, b = 47; printf("Before. a: %d, b: %d\n", a, b); swap(a, b); printf("After. a: %d, b: %d\n", a, b); } Workable?
void swap(int *a, int *b) { int t; t = *a; *a = *b; *b = t; } Calling Function by Passing References #include <stdio.h> main() { int a = 23, b = 47; printf("Before. a: %d, b: %d\n", a, b); swap(&a, &b); printf("After. a: %d, b: %d\n", a, b); } Workable?
void swap(int *a, int *b) { int t; t = *a; *a = *b; *b = t; } Calling Function by Passing References #include <stdio.h> main() { int a = 23, b = 47; printf("Before. a: %d, b: %d\n", a, b); swap(&a, &b); printf("After. a: %d, b: %d\n", a, b); } Workable?
Review: Bubble Sort void BubbleSort(int data[], int n) { int tmp, i, j; for(i=0; i<n-1; i++) for(j=0; j<n-i-1; j++) if(data[j] > data[j+1]){ tmp = data[j]; data[j] = data[j+1]; data[j+1] = tmp; } }
void swap(int *a, int *b) { int t; t = *a; *a = *b; *b = t; } Bubble Sort void BubbleSort(int data[], int n) { int i, j; for(i=0; i<n-1; i++) for(j=0; j<n-i-1; j++) if(data[j] > data[j+1]) swap(&data[j], &data[j+1]); }
BubbleSort(&vals[0], 5); vals 0 100 1 30 2 20 3 75 4 15 Pointers vs. Arrays void swap(int *a, int *b) { int t; t = *a; *a = *b; *b = t; } void BubbleSort(int data[], int n) { int i, j; for(i=0; i<n-1; i++) for(j=0; j<n-i-1; j++) if(data[j] > data[j+1]) swap(&data[j], &data[j+1]); } main() { int vals[5]={100, 30, 20, 75, 15}; BubbleSort(vals, 5); /* ............................ */ } int * int * int *
BubbleSort(&vals[0], 5); vals 0 100 1 30 2 20 3 75 4 15 Pointers vs. Arrays void swap(int *a, int *b) { int t; t = *a; *a = *b; *b = t; } void BubbleSort(int data[], int n) { int i, j; for(i=0; i<n-1; i++) for(j=0; j<n-i-1; j++) if(data[j] > data[j+1]) swap(&data[j], &data[j+1]); } main() { int vals[5]={100, 30, 20, 75, 15}; BubbleSort(vals, 5); /* ............................ */ } int * void BubbleSort(int *data, int n) int *
C Program DesignC Pointers Pointer Expressions and Pointer Arithmetic
Pointer Arithmetic • Increment/decrement pointer • ++ or –- • Add/substract an integer to a pointer • + or += , - or -= • Pointers may be subtracted from each other
Pointer Arithmetic May be meaningless unless performed on an array. • Increment/decrement pointer • ++ or –- • Add/substract an integer to a pointer • + or += , - or -= • Pointers may be subtracted from each other
data data[9] data[8] data[0] data[1] data[2] data[3] data[4] data[5] data[6] data[7] Pointer Arithmetic • Increment/decrement pointer (++ or –-) • Add/substract an integer to a pointer (+ or += , - or -=) • Pointers may be subtracted from each other int data[10]; int i; for(i=0; i<10; i++) data[i] = i; 0 1 2 3 4 5 6 int data[10]; int i, *p; for(i=0, p=data; i<10; i++){ *p = i; p++; } 7 8 9
data data[9] data[8] data[0] data[1] data[2] data[3] data[4] data[5] data[6] data[7] Pointer Arithmetic Which one is performance more effective? • Increment/decrement pointer (++ or –-) • Add/substract an integer to a pointer (+ or += , - or -=) • Pointers may be subtracted from each other int data[10]; int i; for(i=0; i<10; i++) data[i] = i; 0 1 2 3 4 5 6 int data[10]; int i, *p; for(i=0, p=data; i<10; i++){ *p = i; p++; } 7 8 9
data data[9] data[0] data[1] data[2] data[3] data[4] data[5] data[6] data[7] data[8] Pointer Arithmetic int data[10]; int i, *p; for(i=0, p=data; i<10; i++) *p++ = i; • Increment/decrement pointer (++ or –-) • Add/substract an integer to a pointer (+ or += , - or -=) • Pointers may be subtracted from each other 0 1 2 3 4 5 6 int data[10]; int i, *p; for(i=0, p=data; i<10; i++){ *p = i; p++; } 7 8 9
data data[9] data[0] data[1] data[2] data[3] data[4] data[5] data[6] data[7] data[8] Pointer Arithmetic int data[10]; int i, *p; for(i=0, p=data; i<10; i++) *p++ = i; • Increment/decrement pointer (++ or –-) • Add/substract an integer to a pointer (+ or += , - or -=) • Pointers may be subtracted from each other 0 1 2 3 4 5 6 7 int data[10]; int i, *p; for(i=0, p=data; i<10; *p++ = i++) ; 8 9
data 0 1 2 3 4 5 6 7 8 9 data 0 1 2 5 3 4 5 6 7 8 data 0 1 2 5 3 5 6 7 8 8 範例:Insert/Delete Data into/from Arrays void insertAt(int array[], int size, int at, int val); void deleteAt(int array[], int size, int at); insertAt(data, 10, 3, 5); deleteAt(data, 10, 5);
範例:Insert/Delete Data into/from Arrays /* arrayOp.c */ /* insertAt: insert an element into an int array */ void insertAt(int array[], int size, int at, int val) { int *p, *q; p = &array[at]; q = &array[size-1]; while(q > p){ *q = *(q-1); q--; } *p = val; } /* deleteAt: delete an element from an int array */ void deleteAt(int array[], int size, int at) { int *p, *q; p = &array[at]; q = &array[size-1]; while(p < q){ *p = *(p+1); p++; } }
範例:Insert/Delete Data into/from Arrays /* main.c */ void insertAt(int array[], int size, int at, int val); void deleteAt(int array[], int size, int at); void listElements(int array[], int size); main() { int data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; printf("Origin data:\n"); listElements(data, 10); insertAt(data, 10, 3, 5); printf("After calling insertAt(data, 10, 3, 5):\n"); listElements(data, 10); deleteAt(data, 10, 5); printf("After calling deleteAt(data, 10, 5):\n"); listElements(data, 10); }
data[9] data[8] data[6] data[5] data[4] data[7] data[2] data[1] data[0] data[3] data 0 1 2 3 4 5 6 7 8 9 範例:Pointer Arithmetic #include <stdio.h> main() { int data[]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int *p, *q; printf("data[]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\n\n"); p = q = data; printf("p = q = data => p = q = %p\n", data); printf("q - p = %d\n\n", q - p); p++; q += 5; printf("p++; q += 5 => p = %p, q = %p\n", p, q); printf("q - p = %d\n\n", q - p); p -= 3; q--; printf("p -= 3; q-- => p = %p, q = %p\n", p, q); printf("q - p = %d\n\n", q - p); }
data[9] data[8] data[6] data[5] data[4] data[7] data[2] data[1] data[0] data[3] data 0 1 2 3 4 5 6 7 8 9 範例:Pointer Arithmetic #include <stdio.h> main() { int data[]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int *p, *q; printf("data[]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\n\n"); p = q = data; printf("p = q = data => p = q = %p\n", data); printf("q - p = %d\n\n", q - p); p++; q += 5; printf("p++; q += 5 => p = %p, q = %p\n", p, q); printf("q - p = %d\n\n", q - p); p -= 3; q--; printf("p -= 3; q-- => p = %p, q = %p\n", p, q); printf("q - p = %d\n\n", q - p); }
Pointer Comparison • <, <=, ==, >=, > • Usually, they apply to pointers of array’s element • p q is true iff p - q0is true, e.g., p < q is true iff p – q < 0 is true p > q is true iff p – q > 0 is true • NULL == p Test the validity of p, e.g., #define NULL 0 int *p = NULL; /* p may point to somewhere in the following */ . . . . . . . . . . . . . . . if (NULL==p) printf("p is an invalid pointer"); else printf("%d\n", *p);
Pointer Casting • Pointers of the same type can be assigned to each other • If not the same type, a cast operator must be used • Example: main() { int m=5; int *p, *q; char *r; p = &m; /* ok */ q = p; /* ok */ r = p; /* warning */ }
Pointer Casting • Pointers of the same type can be assigned to each other • If not the same type, a cast operator must be used • Example: main() { int m=5; int *p, *q; char *r; p = &m; /* ok */ q = p; /* ok */ r = (char *) p; /* ok */ }
m p q r 範例:Pointer Casting main() { int m; int *p, *q; char *r; m = 0x1ff; /* 511 */ printf("integer m = %d\n\n", m); p = &m; /* ok */ q = p; /* ok */ r = (char *) p; /* ok */ printf("p, q, r all point to m:\n"); printf("p=%p, q=%p, r=%p\n", p, q, r); printf("*p=%d, *q=%d, *r=%d\n\n", *p, *q, *r); *r = '\0'; printf("After setting the 1st byte of m zero, then\n"); printf("*p=%d, *q=%d, *r=%d\n", *p, *q, *r); } 00 ff 01 00 00