12 - Lecture 12| Memory Addresses, Pointers, and Arrays...

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: Lecture 12| Memory Addresses, Pointers, and Arrays Revisited Memory and Addresses Variables and Addresses Pointers and Memory Addresses Addressing and Dereferencing Summary Pointer Assignment and Pointer to void Call-by-Value Call-by-Reference Pointer Arithmetic Arrays, Memory Addresses, and Pointers Passing Arrays to Functions | An Alternative View An Example Readings Exercises CSC 1500 { Lecture 12 1 Overview Memory, variables, addresses, and pointers Call-by-value versus call-by-reference Arrays, memory addresses, and pointers Passing arrays to functions | revisited CSC 1500 { Lecture 12 2 Memory and Addresses 01000001 (represents character ‘A’) 0000 0001 0002 0003 byte 0004 ...... Memory ...... In the lowest level, computers understand only 0's and 1's. Computer memory stores a sequence of 0's and 1's. Each such storage unit is called a bit . Eight bits are grouped together to form a larger storage unit called a byte . Each byte has a unique address for identi cation. Computer memory can thus be viewed as a series of bytes. CSC 1500 { Lecture 12 bit 3 Variables and Addresses 0400 variable c ’A’ 0000 0001 0002 0003 byte 0004 ...... Memory 0400 ...... char c scanf("%c", &c) c is a char variable. denotes the address of variable c in memory. /* user typed 'A' <Enter> */ &c Thus, &c equals 0400. scanf("%c", &c) { causes the input character ('A') to be stored in memory address of c, i.e. 0400. { e ectively stores 'A' into the variable c. CSC 1500 { Lecture 12 4 Pointers and Memory Addresses 0123 variable ptr 0400 0400 variable c ’A’ 0000 0001 0002 0003 byte 0004 ...... 0400 Memory ...... char char c *ptr ptr = &c scanf("%c", ptr) is NOT a char variable. ptr does not store a char. ptr stores the memory address of a char variable. The type of ptr is char pointer. ptr char *ptr { declares the variable ptr. { variable name is ptr, NOT *ptr. { says that ptr is a char pointer. CSC 1500 { Lecture 12 5 Addressing and Dereferencing int a, b, *p a ? /* declares 3 variables a, b and p without initialization b ? p ? */ a=b=7 p = &a /* store integer value 7 to the two int variables */ /* store the address of an int variable a to p */ a 7 b 7 p Now we can use pointer p to access the value of variable a. By using the indirection operator *. The expression *p is equivalent to the variable to which p points (refers to). Example, printf("a = %d\n", *p) /* prints value of a, i.e. 7 */ * Not to be confused with the use of declared. p when pointer p is is a char pointer variable while *p is a char variable . is 0400. After the statement p = &a, the value of variable p becomes 0400. *p then refers to the content of the memory location whose address is stored in variable p, i.e. 0400. CSC 1500 { Lecture 12 An alternative view: Suppose the memory address of variable a 6 *p = 3 printf ("a = %d\n", a) /* 3 is printed */ a 3 b 7 p When *p appears on the L.H.S. of an assignment, it means the value on the R.H.S. is to be written onto the memory location to which p points. p = &b a 3 b 7 p *p = 2 * *p - a printf("b = %d\n", b) /* is equivalent to "b = 2 * b - a " */ /* 11 is printed */ a 3 b 11 p We do not really care about the actual memory address stored. Our concern is the data object to which p is pointing. CSC 1500 { Lecture 12 7 Summary #include <stdio.h> int main(void) { int i, *iptr printf ("Enter an integer? ") scanf("%d", &i) /* use format specifier "%p" to print a memory address */ printf ("\nMemory address of variable i = %p\n", &i) printf ("Value of variable i = %d\n", i) iptr = &i printf ("\nValue of variable iptr = %p\n", iptr) printf ("Value of data object pointed to by iptr = %d\n", *iptr) printf ("\nMemory address of iptr itself = %p\n", &iptr) iptr = NULL /* NULL is defined in stdio.h, means nothing */ printf ("\niptr now points to nothing!\n") printf ("\nThe statement \"*iptr = 3 \" produces a runtime error!\n") *iptr = 3 /* error message or hang... */ return 0 } Enter an integer? 99 Memory address of variable i = effffc0c Value of variable i = 99 Value of variable iptr = effffc0c Value of data object pointed to by iptr = 99 Memory address of iptr itself = effffc08 iptr now points to nothing! The statement "*iptr = 3 " produces a runtime error! you will see...] null pointer assignment OR] hang!!! CSC 1500 { Lecture 12 8 Pointer Assignment and Pointer to void In ANSI C, one pointer can be assigned to another only when they both have the same type. Example, int char x, *ptr1, *ptr2 c, *ptr3=&c /* ptr1 points to x */ /* valid, both ptr1 and ptr2 point to x */ /* invalid */ ptr1 = &x ptr2 = ptr1 ptr2 = ptr3 In pointer assignment, the value of a pointer (an address) is copied to another pointer variable. E ectively both pointer variables refer to the same memory location, i.e. the same data object. Pointer assignment is allowed when one of the operands is of type \pointer to void". (void means no type or any type) We can think of void * as a generic pointer type. Not to be confused with NULL (means 0 or nothing). Example, #include <stdio.h> int main(void) { int char void x, *xptr=&x *cptr *vptr /* valid */ /* valid */ vptr = xptr cptr = vptr return 0 } CSC 1500 { Lecture 12 9 Call-by-Value #include <stdio.h> void wrong_swap (int, int) int main(void) { int x=33, y=99 printf ("x=%d, y=%d\n", x, y) wrong_swap(x, y) printf ("x=%d, y=%d\n", x, y) return 0 } void wrong_swap (int x, int y) { int tmp printf ("\t swap!\n") printf ("\t x=%d, y=%d\n", x, y) tmp = x x=y y = tmp printf ("\t x=%d, y=%d\n", x, y) } x=33, y=99 swap! x=33, y=99 x=99, y=33 x=33, y=99 CSC 1500 { Lecture 12 10 int main(void) { int x=33, y=99; ...... wrong_swap(x, y); ...... } x 33 y 99 Memory void wrong_swap(int x, int y) { int tmp; ...... ...... } x 33 y 99 tmp ? Whenever variables are passed as arguments to a function, their values are copied to the corresponding function parameters. The parameters have a lifespan identical to the lifespan of the function. That is, the parameters are created when the function is entered, and are destroyed (freed from memory) when the function returns. No matter how the value of the parameters changes, the variables in the calling environment (main in the example) are not changed. CSC 1500 { Lecture 12 11 Call-by-Reference #include <stdio.h> void swap (int *, int *) int main(void) { int x=33, y=99 printf ("x=%d, y=%d\n", x, y) swap(&x, &y) printf ("x=%d, y=%d\n", x, y) return 0 } void swap (int *p, int *q) { int tmp printf ("\t swap!\n") printf ("\t *p=%d, *q=%d\n", *p, *q) tmp = *p *p = *q *q = tmp printf ("\t *p=%d, *q=%d\n", *p, *q) } x=33, y=99 swap! *p=33, *q=99 *p=99, *q=33 x=99, y=33 CSC 1500 { Lecture 12 12 int main(void) { int x=33, y=99; ...... swap (&x, &y); ...... } 0400 x 33 0481 y 99 Memory void swap(int *p, int *q) { int tmp; ...... ...... } p 0400 q 0481 tmp ? Call-by-Reference is accomplished by Passing an address as an argument when the function is called. Declaring a function parameter to be a pointer. Using the dereferenced pointer in the function body. CSC 1500 { Lecture 12 13 Pointer Arithmetic #include <stdio.h> int main(void) { int char ivar, *iptr cvar, *cptr iptr = &ivar cptr = &cvar printf ("Original\n") printf ("iptr = %p (hexadecimal)\n", iptr) printf ("cptr = %p (hexadecimal)\n", cptr) printf ("\nIncremented\n") printf ("iptr = %p (hexadecimal)\n", ++iptr) printf ("cptr = %p (hexadecimal)\n", ++cptr) return 0 } Original iptr = effffc0c (hexadecimal) cptr = effffc07 (hexadecimal) Incremented iptr = effffc10 (hexadecimal) cptr = effffc08 (hexadecimal) If a pointer variable is incremented, its value is actually increased by sizeof(type) where type is the data type that the pointer points to. This allows the pointer to point to the next piece of data item in the memory meaningfully. Other arithmetic operators (<p> + <i>, <p> - <i>, <p> - <p>, ...) when applied to pointer variables behave similarly. CSC 1500 { Lecture 12 14 Arrays, Memory Addresses, and Pointers One Dimensional ad dr es s ad dr es s ad dr es s ad dr es s ad dr es s list[0] [1] [2] [3] [4] int list[5]; list Assuming that sizeof(int)==4. Assuming that list 0] begins at memory address 1000. { list 1] begins at 1004. { list 2] begins at 1008. { etc. An array name without subscript (list) denotes the address of the rst element of the array. That is, list==&list 0]. Starting address of list list i] + sizeof(int) 10 00 is given by i CSC 1500 { Lecture 12 10 04 10 08 10 12 10 16 15 Two Dimensional matrix 1000 int matrix[3][4]; 1004 1008 1012 1016 1020 1024 1028 1032 1036 1040 address 1044 matrix[0][0] matrix[0][1] matrix[0][2] matrix[0][3] matrix[1][0] matrix[1][1] matrix[1][2] matrix[1][3] matrix[2][0] matrix[2][1] matrix[2][2] matrix[2][3] Assuming that sizeof(int)==4. Assuming that matrix 0] 0] begins at address 1000. { matrix 0] 1] begins at 1004. { matrix 0] 2] begins at 1008. { etc. An array name without subscript (matrix) denotes the address of the rst element of the array (matrix==&matrix 0] 0]). For a 2-dimensional int array matrix ROW] COL], the starting address of matrix i] j] is given by matrix + sizeof(int) (COL i + j) CSC 1500 { Lecture 12 16 Passing Arrays to Functions | An Alternative View #include <stdio.h> #define SIZE 5 int sum(int *, int) int main(void) { int list SIZE] int i for (i=0 i<SIZE i++) { printf("number = ? ") scanf("%d", &list i]) } printf("sum = %d\n", sum(list, SIZE)) return 0 } int sum (int *ptr, int size) { int sum=0 while (size) { sum += *ptr ptr++ size-} return sum } Note: ===== *ptr *(ptr+1) *(ptr+2) ... *(ptr+i) == list 0] == list 1] == list 2] == list i] When an array is being passed, the name of the array is used as the parameter. It's actually the base address of the array to be passed. The array elements are not copied. Call-by-Reference!! What's the di erence between the two methods? int sum (int list ], int size) int sum (int *ptr, int size) CSC 1500 { Lecture 12 17 An Example #include <stdio.h> #define SIZE 4 int skip_sum(int *, int) int main(void) { int n, array SIZE] = {1, 2, 3, 4} while (1) { printf("Skip how many? ") scanf("%d", &n) if (n < 0) break else printf("Sum = %d\n", skip_sum(array, n)) } printf ("Bye!\n") return 0 } int skip_sum(int *ptr, int skip) { int i, sum=0 ptr = ptr + skip for (i=1 i <= (SIZE-skip) sum += *ptr return sum } i++, ptr++) Skip how Sum = 9 Skip how Sum = 7 Skip how Sum = 4 Skip how Sum = 0 Skip how Bye! many? 1 many? 2 many? 3 many? 4 many? -1 CSC 1500 { Lecture 12 18 Readings Chapter 8, Sections 8.1 { 8.4 Chapter 8, Section 8.9 Chapter 8, Section 8.12 Chapter 9, Sections 9.3 { 9.4 Exercises Chapter 8, Exercises 2, 5, 6, 7, 10 Chapter 9, Exercises 3, 4 2 End of Lecture 12 CSC 1500 { Lecture 12 19 ...
View Full Document

Ask a homework question - tutors are online