490 likes | 585 Vues
Structured Programming Instructor: Prof. K. T. Tsang. Lecture 7: Pointer 指针. Memory cells and addresses. Computer memory is a sequential collection of storage-cells for data. Each cell is 1 byte in size and has an address associated with it.
E N D
Structured ProgrammingInstructor: Prof. K. T. Tsang Lecture 7: Pointer 指针
Memory cells and addresses Computer memory is a sequential collection of storage-cells for data. Each cell is 1 byte in size and has an address associated with it. Typically, the addresses are numbered consecutively, starting from zero. The last address depends on the memory size. A computer with 64k memory will have its last address as 65,535.
Address of Variable When a variable is declared, the C/C++ compiler will allocate a block of cells somewhere in the memory to hold the value of the variable, either during compile-time or in run-time. The size of this block of cells will depend on the data type of the variable being declared. The address of the first cell in this block is the address of the variable.
Example In a machine with 4-byte integer, when we declare and initialize int an_int = 789; 4 adjacent memory cells are reserved for the variable an_int and occupied by the integer 789. The address of the first cell in this block is the address of an_int. Address of an_int 19 20 21 22 23 24 25 26 27 28 Cell address 789 4 bytes occupied by an_int
4 essential attributes特征of a variable name (identifier) data type(size of memory block) address value 789 an_int 20020
Memory address: 1020 1024 … … 100 … … … a Address Operator &The “address of ” operator (&) gives the memory address of the variable(地址算符)Usage: &variable_name int a = 100; //To get the value, use the variable name printf(“a=%d\n”, a); //prints 100 //To get the memory address, add the address //operator before the variable name printf(“address of a: %d\n”, &a); //prints 1024
Address Operator & Try the following code to get the addresses of variables. #include <stdio.h> void main(){ int a, b; a = 88; b = 100; printf("The address of a is: %x”, &a); printf("The address of b is: %x”, &b); } Address is usually a large number, so print it in hex.
Pointer指针 • A pointer constant指针常数is the memory address of a variable. • A pointervariable指针变量is a variable used for storing the address of a variable. • Using pointer (i.e. data type and memory address), we can access the value of the variable stored in the memory indirectly.
Pointer Types C/C++ has pointer types for each type of data, e.g. • Pointers to intdata type • Pointers to chardata type • Pointers to user-defined data structure Even pointers to pointers • Pointers to pointers to inttype
Pointer Variables • A pointer variable is a specific box for storing a memory address • Declaration of Pointer variables type* pointer_name;//style 1 or type *pointer_name;//style 2 or type *pointer_name;//style 3 where typeis the type of data pointed to (e.g. int, char, double) by the pointer.
Declaration of Pointers The style 2 (in previous slide) is more popular because it is more convenient to have multiple declaration, and accessing the target value, e.g. int i1, i2, *ip; //ip is a pointer ip = &i1; //initialize ip by address of i1 *ip = 23; //assign 23 to i1 float f1 = 1.33; ip = &f1; //error, why?
Memoryaddress: 0x1020 0x1024 0x1034 … 88 100 … 1024 … a p Pointer Variables int a = 100; int *p = &a; printf(“%d %x\n”, a, &a); printf(“%x %x\n”, p, &p); The value of pointer p is the address of variable a. A pointer is also a variable, so it has its own memory address.
Memoryaddress: 0xa23b 0xa24b … 88 100 … 1024 … a p De-reference Operator *取值算符We can access to the value stored in the variable pointed to by preceding the pointer with the dereference(indirection) operator (*), int a = 100; int *p = &a; printf(“%d %x\n”, a, &a); printf(“%d %x %x\n”, *p, p, &p); Result is: 100 a23b 100 a23b a24b
Example: * operator int numberA, *p, m; numberA = 145; p = &numberA; //initialize p m = *p; //assign 145 to m *p = 31; //assign 31 to variable pointed to by p printf(“%d\n”, numberA ); //31
Don’t get confused • Declaring a pointer means only that it is a pointer: int *p;//p is an integer pointer • Don’t be confused with the de-reference operator, which is also written with an asterisk (*). They are simply two different tasks represented with the same sign int a = 100, b = 88, c = 8; int *p1 = &a, *p2, *p3 = &c; p2 = &b; // p2 points to b p1 = p2; // p1 points to b b = *p3; //assign c to b printf(“%d%d%d\n”, a, b, c); //result is: 888
Pointer Example Result is: value1=10 ; value2=10 value1=20 ; value2=20 #include <stdio.h> int main (){ int value1 = 5, value2 = 15; int *p1, *p2; p1 = &value1; // p1 = address of value1 p2 = &value2; // p2 = address of value2 *p1 = 10; // value pointed to by p1=10 *p2 = *p1; // value pointed to by p2= value // pointed to by p1 printf("value1=%d ; value2=%d\n“, value1, value2); p1 = p2; // p1 = p2 (pointer value copied) *p1 = 20; // value pointed to by p1 = 20 printf("value1=%d ; value2=%d\n“, value1, value2); return 0; }
Pointer vs. reference • Both are used to indirectly access variables. • Reference always refers to a data object. It is an errorto define a reference without initializing it, while it is OK to do so for a pointer. • It is an error to define a reference to another reference, but it is OK to define a pointer to another pointer.
Pointer vs. reference - 2 • Once initialized, a reference always refers to the same data. Pointer can point to different data by re-assignment. int i1=17, i2=210; int &r1=i1, &r2=i2; r1=r2;//assigns 210 to i1 int *p1=&i1, *p2=&i2; p1=p2;//p1 now points to i2
Pointer to other pointer Pointer variable has its own address. So we can define a pointer points to another pointer. int ival = 67; int *p = &ival; //pointer to ival int **q; //declaringapointer to other pointer q = &p; //pointer to pointer p
Pointer to Pointer What is the output? 58 58 58
More Pointer to Pointer addresses 5534 2234 3334 4434 p q r s Int a 58 2234 3334 4434 5534 Pointer to int Pointer to pointer to int Pointer to pointer to pointer to int Pointer to pointer to pointer to pointer to int • int a = 58; • int *p = &a; • int **q = &p; • int ***r = &q; • int ****s = &r; • q = &a //illegal! • s = &q //illegal!
Pointer and array When we use the name of an array in an expression, that name is automatically converted into a pointer to the first element of the array. int ia[] = {5, 6, 1, 3}; int *p = ia; //p points to ia[0] int *q = &ia[4]; //q points to ia[4]
Array Name is a pointer constant #include <stdio.h> void main (){ // Demonstrate array name is a pointer constant int a[5]; printf("Address of a[0]: %x\n”, &a[0]); printf("Name as pointer: %x\n“, a); } /* example of result (system dependent): Address of a[0]: 0x0065FDE4 Name as pointer: 0x0065FDE4 */
Pointer Arithmetic -- to compute a pointer to an array element by adding /subtracting an integral value to/from a pointer to another array element int ia[] = {5, 6, 4, 1, 3}; int *p1 = ia; //p1 points to ia[0] int *p2 = ia + 4; //p2 points to ia[4] int *p3 = ia + 6; //error: ia + 6 is invalid address
Pointer Arithmetic 2 4 6 p - 1 a 8 p a + 1 22 p + 1 a + 2 p + 2 a + 3 p + 3 a + 4 Given a pointer p, p+n refers to the element that is offset from p by n positions. int a[5] = {2,4,6,8,22}; int *p = &a[1];
2 a 4 a + 1 6 a + 2 8 a + 3 22 a + 4 Dereferencing Array Pointers a[0] or *(a + 0) a[1] or *(a + 1) a[2] or *(a + 2) a[3] or *(a + 3) a[4] or *(a + 4) *(a+n) is identical to a[n]
Use of array pointer const int arr_sz = 6; int ia[arr_sz] = {5, 6, 1, 2, 4, 3}; for (int *p1 = ia; p1 <= ia+arr_sz; ++p1) printf(“%d ”, *p1); //print current element printf(“\n”);
Array of Pointers & Pointers to Array int a = 1, b = 2, c = 3; int *p[5]; p[0] = &a; p[1] = &b; p[2] = &c; int list[5] = {9, 8, 7, 6, 5}; int *p; P = list;//points to 1st entry P = &list[0];//points to 1st entry P = &list[1];//points to 2nd entry P = list + 1; //points to 2nd entry a p b c A pointer to an array An array of Pointers
NULL pointer • NULL is a special value that indicates an empty pointer • If you try to access a NULL pointer, you will get an error • “NULL” is defined as a preprocessor constant in cstdlib int *p = NULL; //ok p = 0; //ok, literal ‘0’ for null pointer cout << p << endl; //prints 0 cout << &p << endl; //prints address of p cout << *p << endl; //Error! int zero = 0; int *p1 = zero; // error, cannot use integer zero instead of ‘0’ int *p2 = 7889; //error, cannot be assigned with a fixed number
Good programming practice tips • Using un-initialized pointer is dangerous. • If you have to define a pointer without assigning a pointer constant to it, set it to NULL first.
String pointer This is the old way we learned to declare & initialize a string. S1 is the pointer to the first element of the character array. char s1[ ] = “A string"; while (*s1) { printf(“%c”, *s1); ++s1; } printf(“\n”); char *s2 = “Another string"; char *s3 = s2; printf(“%s %s %s\n”, s1, s2, s3) This creates a string to hold all the characters and stores the address of the first character in the string pointer variable s2. Assign s2 to another string pointer variable s3
String copy using pointer char* str_copy(char *s1, char *s2) { int i = 0; while (*s2 != '\0') { *s1 = *s2; ++s1; ++s2; i++; } *s1 = *s2; return s1-i; } #include <stdio.h> char* str_copy(char *s1, char *s2); int main() { char *s3 = “This is a string!"; printf(“s3= %s\n”, s3); char *s4; s4 = str_copy(s4, s3); printf(“s4= %s\n”, s4); return 0; }
Using constto protect argumentso that its value cannot be changed float mean (int n, const float *a) { float sum = 0.0; for (int i=0; i<n; i++) sum += *(a+i); return (sum/(float)n); } In general if we prototype: void fun1(const int *p) then inside the definition of fun1 we cannot have a statement like: *p = 10;
Exercise Following last example, use pointer to write a function with the prototype: char* strcat(char* s1, constchar* s2); to concatenate(连接) 2 strings s1 & s2 together. Use this function in a program to show that it works.
Pointer as function arguments: Compare this with call by reference in Lecture 7 example: swap void exchange (int *, int *); main() { int x = 100, y = 28; printf(“before exchange: x=%d y=%d”, x, y); exchange ( &x, &y); printf(“after exchange: x=%d y=%d”, x, y); } void exchange (int *a, int *b) { int t = *a; *a = *b; *b = t; }
Bubble Sort using pointers void sort (int m, int *x) { int i, j, temp; for (i=1; i<m; i++) for (j=1; j<=m-i; j++) { if (*(x+j-1) >= *(x+j) ) { temp = *(x+j-1); *(x+j-1) = *(x+j) ; *(x+j) = temp ; } } }
Bubble Sort using pointers void sort (int m, int *x) { int i, j, temp; for (i=1; i<m; i++) for (j=1; j<=m-i; j++) { if (*(x+j-1) >= *(x+j) ) exchange(x+j-1, x+j); } }
Using bubble sort with pointer #include <stdio.h> void sort (int m, int *x); void main() { int score[ ] = { 11, 9, 19, 15, 22, 7}; for (int i=0; i<6; i++) printf(“%d ”, score[i]); printf(“\n”); int *ia = score; sort(6, ia); for (int i=0; i<6; i++) printf(“%d ”, score[i]); printf(“\n”); }
Bubble Sort using array void sort (int m, int x[ ]) { int i, j, temp; for (i=1; i<m; i++) for (j=1; j<=m-i; j++) { if (x[j-1] >= x[j] ) { temp = x[j-1]; x[j-1] = x[j] ; x[j] = temp ; } } }
Using arraybubblesort #include <stdio.h> void sort (int m, int x[ ]); void main() { int score[ ] = { 31, 9, 19, 15, 22, 7}; for (int i=0; i<6; i++) printf(“%d ”, score[i]); printf(“\n”); sort(6, score); for (int i=0; i<6; i++) printf(“%d ”, score[i]); printf(“\n”); }
Library function for input - scanf “scanf” read input data from the keyboard, similar to “printf” output data to the terminal. First argument to “scanf” is the format string (enclosed by “ ”) similar to the format string used by “printf”. Second (and 3rd…) argument to “scanf” is an address to the input data. int number, u, v; printf (“Please input an integer.\n”); scanf ( “%i”, &number); printf (“Please input 2 positive integers.\n”); scanf (“%d%d”, &u, &v); printf (“Got 2 positive integers: %d %d\n”, u, v);
Important scanf (“format string”, arg1, arg2, arg3,…) where arg1…argn are addresses to data. scanf ( “Enter a number\n%d”, &number); Input data must be separated by space, tab or newline. If you forget to put “&” in front of the variables in the arguments of “scanf”, the result could be a “segmentation violation core dumped” or “illegal memory access” error.
Example: find greatest common divisor • Given 2 positive integers u & v. • If v equals zero, then the gcd is u. • Find temp=u%v, then set u=v, v=temp, and go back to previous step. #include <stdio.h> void main () { int u, v, temp; printf (“Please input 2 positive integers.\n”); scanf (“%i %i”, &u, &v); if(u<v) exchange(&u, &v); //make sure u>v printf (“2 positive integers are: %d %d\n”, u, v); while (v != 0) { temp = u%v; u = v; v = temp; } printf (“The greatest common divisor is: %d\n”, u); }
Inputting character string with scanf “scanf” can be used with %s format to read in a string of characters up to a blank space, tab or newline character. char str[99]; scanf (“%s”, str); //no ‘&’ needed The 2 statements above have the effect of reading a character string typed into the terminal and storing it in the array str.
More examples: inputting strings char s1[99], s2[99], s3[33]; scanf (“%s %s %s”, s1, s2, s3); With the input text line: “happy new year\n” results in s1 = “happy” s2 = “new” s3 = “year”
Summary—what you should have learned from this Lecture • Variable address • Pointer uses the variable address to access the variable value indirectly. • “Address of” operator: & • “De-reference” or “Value contained” operator: * • Array name as a pointer • Pointer arithmetic • Pointer vs. reference • String pointer: char* • Using “scanf” to input data from terminal