450 likes | 472 Views
Pointers and Arrays. Kernighan/Ritchie: Kelley/Pohl:. Chapter 5 Chapter 6. Lecture Overview. Arrays Pointers Call-by-reference Arrays, pointers and pointer arithmetic Dynamic Memory Allocation. Arrays. Programs often use homogeneous data For example:
E N D
Pointers and Arrays Kernighan/Ritchie: Kelley/Pohl: Chapter 5 Chapter 6
Lecture Overview • Arrays • Pointers • Call-by-reference • Arrays, pointers and pointer arithmetic • Dynamic Memory Allocation
Arrays • Programs often use homogeneous data • For example: • When the size of the data is too large, arrays are a better solution: int grade0, grade1, grade2; int grades[3];
Arrays • It is good programming practice to define the size of an array as a symbolic constant • The standard idiom for processing an array defined this way is using a for loop #define SIZE 8 int array[SIZE]; for (i = 0; i < SIZE; i++) printf ("%d ", array[i]);
Array Initialization • A special format exists for initializing arrays • If the list of initializers is shorter than the array, the rest of the array is set to zero • In this case, the last two elements (f[3] and f[4]) will be initialized to zero float f[5] = { 0.0, 1.0, 2.0, 3.0, 4.0 }; float f[5] = { 0.0, 1.0, 2.0 };
Array Initialization • Depending on its storage class, an array may or may not be automatically initialized • static and external arrays are always initialized – this is done by setting all of their elements to zero • automatic arrays will not necessarily be initialized (depends on the compiler), and thus they should be assumed to contain garbage
Array Initialization • If an array is declared without a size, it is implicitly given a size according to the number of initializers • Thus, the following two array declarations are equivalent: int a[] = {2, 3, 5, -7}; int a[4] = {2, 3, 5, -7};
Array Initialization • Character arrays may be initialized in the same way: • However, since character arrays serve as strings in C, the following short-cut is also available (equivalent to the above): char s[] = {'a', 'b', 'c', '\0'}; char s[] = "abc";
Lecture Overview • Arrays • Pointers • Call-by-reference • Arrays, pointers and pointer arithmetic • Dynamic Memory Allocation
Pointers • A simple variable in a program is storedin a certain number of bytes, at some particular memory location (or address) • Pointers are used to access memory and manipulate addresses • If v is a variable, then &v is the addressin memory where its value is stored
Pointers • Memory addresses are values that can be manipulated much like integer values • The following declares a pointer to int: • Examples of assignment to the pointer p: int *p; p = 0; p = NULL; /* equivalent to p = 0; */ p = &i; /* i must be an integer. */ p = (int *)1776; /* an absolute memory address */
Pointers • A basic example of how the pointer mechanism works: • We think of the pointer p is an arrow, which at this stage is pointing to nothing: int a = 1, b = 2, *p; a b p ? 1 2
Pointers • Now, assume that the next line of code is: • After this statement, the memory contentswill look like this: p = &a; a b p 1 2
Pointers • Finally, consider the following assignment: • This assigns the value pointed to by p to b • Since p points to a, this is equivalent to the statement: b = *p; b = a;
Pointers – Example • Print the address and value of a variable: #include <stdio.h> int main() { int i = 7; int *p = &i; printf (" Value of i: %d\n", *p); printf ("Location of i: %p\n", p); return 0; }
Pointers – Example • The output of the program in our system: • The actual location of a variable in memory is system-dependent • The variable p is of type int *, and its initial value is &i • The operator * dereferences p Value of i: 7 Location of i: 0xbffff924
Pointer Expressions • Evaluating some pointer expressions:
Pointer Expressions • The third line tries to assign the address of a double variable to a pointer to int • In the fourth line: • The first '*' is the multiplication operator • The second '*' is the dereference operator • In the fifth line, r is assigned the address of j, and then another assignment multiplies *r (which now means j) by *p
Lecture Overview • Arrays • Pointers • Call-by-reference • Arrays, pointers and pointer arithmetic • Dynamic Memory Allocation
Call-by-reference • In C, all parameters are passed by value • In other languages, it is possible to pass parameters by reference, allowing the called function to modify them • The same effect can be achieved in C, using pointers as function arguments
Call-by-reference – Example • Let us try to write a function that swaps the values of its two arguments: • This will have no effect on a and b: void try_to_swap (int x, int y) { int tmp; tmp = x; x = y; y = tmp; } try_to_swap (a, b);
Call-by-reference – Example • However, using pointers we can write the swap() function as follows: • This will swap the values of a and b: void swap (int *px, int *py) { int tmp; tmp = *px; *px = *py; *py = tmp; } swap (&a, &b);
Lecture Overview • Arrays • Pointers • Call-by-reference • Arrays, pointers and pointer arithmetic • Dynamic Memory Allocation
Arrays and Pointers • Arrays and pointers are very similar • An array name is actually a pointer to the first element in the array • Similarly, a pointer can be subscripted just as if it were an array • However, there is one major difference: the value of a pointer can change, while an array points to a fixed address
Arrays and Pointers • Suppose that a is an array and that i is an int, then a[i] is equivalent to *(a + i) • Similarly, if p is a pointer, then p[i] is equivalent to *(p + i) • This means that we can use array notation with pointers, and vice versa
Arrays and Pointers – Example #include <stdio.h> #define SIZE 7 int main() { int a[SIZE] = {12, 32, 434, 43, 26, 873, 43}; int i; for (i = 0; i < SIZE; i++) printf ("%d ", a[i]); printf ("\n"); return 0; } 12 32 434 43 26 873 43
Arrays and Pointers – Example • The array traversal loop in the previous example can be written in different ways: for (i = 0; i < SIZE; i++) printf ("%d ", *(a + i)); int *pa = a; for (i = 0; i < SIZE; i++) printf ("%d ", *(pa++)); for (i = 0; i < SIZE; i++) printf ("%d ", i[a]);
Pointer Arithmetic • Pointer arithmetic is one of the most powerful features of C • If the variable p is a pointer to a particular type, then the expression p + 1 yields the correct machine address for storing or accessing the next variable of that type • Other expressions may be used, such as: p++, p + i or p += i
Pointer Arithmetic – Example #include <stdio.h> int main() { double a[2], *p, *q; p = a; /* points to base of array */ q = p + 1; /* equivalent to q = &a[1]; */ printf ("%d\n", q - p); printf ("%d\n", (int)q - (int)p); return 0; } 1 8
Pointer Arithmetic – Example • The previous output assumes that a double is stored in 8 bytes • p points to a double and q points to the next double, therefore the difference in array elements is 1 • However, the difference in actual memory locations is 8
Arrays as Function Arguments • In a function definition, a parameter that is declared as an array is actually a pointer • For convenience, bracket notation is also allowed, but the two are equivalent • Inside the function, the parameter may be treated as a pointer, as an array, or alternately as both
Arrays as Function Arguments – Example • The function header may be replaced with: /* n is the size of a[]. */ double sum (double a[], int n) { int i; double sum = 0.0; for (i = 0; i < n; ++i) sum += a[i]; return sum; } double sum (double *a, int n)
Lecture Overview • Arrays • Pointers • Call-by-reference • Arrays, pointers and pointer arithmetic • Dynamic Memory Allocation
Dynamic Memory Allocation • Until now we have seen two ways of allocating memory: • At compile time, for static and global variables • During run-time, for automatic (local) variables • Both types require knowing the amount of memory that should be allocated beforehand (when the program is written)
Dynamic Memory Allocation • Sometimes there is a need to explicitly tellthe system to allocate memory during the program's operation • This is called dynamic allocation • Memory is allocated using the library function malloc(), defined in stdlib.h • Other functions exist, such as calloc() or realloc() but we will not discuss them here
Dynamic Memory Allocation • Dynamic allocation is used to create space for arrays, structures and unions • The function malloc() takes a single argument of type size_t, and returns: • NULL, if the required amount of memory cannot be allocated, or: • A pointer of type void *, which points to a memory block of the requested size
Dynamic Memory Allocation • The memory allocated by malloc() is not initialized to any value • Space that was dynamically allocated is not returned to the system upon function exit • The space must be freed explicitly by the programmer, through a call to free(ptr) • ptr is a pointer that points to a block of space previously allocated by malloc()
Dynamic Memory Allocation – Example 1 #include <stdio.h> int main() { float arr[20]; arr[0] = 2; printf ("Value of first cell: %f\n", *arr); arr[7] = 17; printf ("Value of 8th cell: %f\n", *(arr + 7)); return 0; }
Wrong! Dynamic Memory Allocation – Example 1 #include <stdio.h> int main() { float *arr; arr[0] = 2; printf ("Value of first cell: %f\n", *arr); arr[7] = 17; printf ("Value of 8th cell: %f\n", *(arr + 7)); return 0; }
OK Dynamic Memory Allocation – Example 1 #include <stdio.h> int main() { float *arr = (float *)malloc (20 * sizeof (float)); arr[0] = 2; printf ("Value of first cell: %f\n", *arr); arr[7] = 17; printf ("Value of 8th cell: %f\n", *(arr + 7)); free (arr); return 0; }
Dynamic Memory Allocation – Example 2 int main() { int *grades, num_grades; int i, sum = 0; printf ("Please enter number of grades: "); scanf ("%d", &num_grades); grades = (int *)malloc (num_grades * sizeof (int)); printf ("Please enter grades: "); for (i = 0; i < num_grades; i++) scanf ("%d", &grades[i]); for (i = 0; i < num_grades; i++) { printf ("Grade %d: \t%d\n", i + 1, grades[i]); sum += grades[i]; } free (grades); printf ("Average: \t%d\n", sum / num_grades); }
Dynamic Memory Allocation – Example 2 • The output of the previous program: Please enter number of grades: 5 Please enter grades: 10 5 18 19 8 Grade 1: 10 Grade 2: 5 Grade 3: 18 Grade 4: 19 Grade 5: 8 Average: 12
Dynamic Memory Allocation – Example 2 • When calling malloc() we need to take into account: • The number of elements required • The size of each element (using sizeof()) • The type of the pointer returned by malloc() is void *, and therefore we need to cast it into the required type