720 likes | 900 Views
CSCI 171. Presentation 11 Pointers. Pointer Basics. Why use pointers?. Some routines can be more efficiently written with pointers Some routines need pointers. Memory Usage. Programmer declares a variable int x; Compiler sets aside memory 4 bytes for an integer
E N D
CSCI 171 Presentation 11 Pointers
Why use pointers? • Some routines can be more efficiently written with pointers • Some routines need pointers
Memory Usage • Programmer declares a variable • int x; • Compiler sets aside memory • 4 bytes for an integer • Memory has a unique address • Address and variable name are associated • Address is hidden from the programmer
Memory Address • Address is an integer • Can be printed out with %p • result represents a segment and an offset • what segment of memory the location is in • what offset (how far from the start of the segment) the location is • Most compilers show the two separated by a colon • Code Warrior does not
Pointers • Address can be stored in another variable • pointer • Pointer - variable that contains the address of another variable
Using Pointers • Pointers must be declared before use • Names must be unique • Declaration: • typename * ptrname; • int * x; • * - Indirection operator • Informs the compiler that the variable is a pointer
Initializing Pointers • Pointers must be initialized • Always initialize pointers to NULL • int * ptr = NULL; • Symbolic constant for 0 • Impossible to know what uninitialized pointers are pointing to • could be anywhere in memory
Address of Operator • & - address of operator • int x = 3; • &x is interpreted as ‘the address of x’ • Sample code: • int x = 3; • int * y = NULL; • y = &x;
Using Pointers • Once a pointer has been declared and initialized it can be used • When indirection operator (*) precedes a pointer, it refers to the contents of the variable to which it points
Using Pointers - Example • int x = 3; • int *y = NULL; • y = &x; • printf(“%d”, *y); • The preceding code results in 3 printed to the screen
Accessing InformationDefinitions • Direct Access - accessing contents of a variable using the variable name • Indirect Access - accessing the contents of a variable by using a pointer to the variable
Accessing Information • Assume ptr is a pointer variable that points to the variable var • *ptr and var each refer to the contents of var • ptr and &var each refer to the address of var
int x = 3, *y = NULL; y = &x; printf(“%d”, x); printf(“%d”, *y); printf(“%p”, &x); printf(“%p”, y); } Equivalent Statements Using Pointers - Example } Equivalent statements
Arrays and Pointers • The name of an array is a pointer to the array • points to the first byte of the first element • remains fixed throughout program execution • Example: • if int x[10] is an array declaration, then • x and &x[0] are equivalent • both represent the addresses of the first array element
Arrays and Pointers • Consider the following code: • int array[3] = {1, 2, 3}, *ptr = NULL, z=2; • ptr = array; • array points to the first element in the array • cannot be changed • array = &z; causes a compiler error • ptr points to the first element in the array • can be changed • ptr = &z; does not cause a compiler error
Pointer Arithmetic • Pointers are often manipulated arithmetically • incremention • decrementation • The compiler ‘knows’ the size of a data type, and will increment the address accordingly • adding 1 to an integer pointer increments the address by 4 • integers take up 4 bytes of space
Using pointer arithmetic - Ex. 1 • Print out the contents of a 10 element integer array using pointer arithmetic • int main( void ) { • int x[10] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}, *y = NULL, count; • y = x; • for (count = 0; count < 10; count++) • printf("%d ", *y++); • }
Using pointer arithmetic - Ex. 2 • #include <stdio.h> • int main( void ) { • int x[5] = {2, 4, 6, 8, 10}, *y = NULL, count = 0; • char a[5] = {‘a’, ‘b’, ‘c’, ‘d’, ‘e’}, *b = NULL; • y = x; • b = a; • for (count = 0; count < 5; count++) • { • printf("\n%d ", *y++); //incrementing y increments the pointer 4 bytes • printf("\n%c ", *b++); //incrementing b increments the pointer 1 byte • } • }
Other pointer arithmetic • Incrementation, decrementation are valid • +, - • must be an integer (compiler error if not) • Other arithmetic is not valid • *, /, %, etc.
Pointers and Functions • Arrays cannot be passed into functions, but pointers can • In our programs when we pass in an array, we have actually passed in a pointer • Prototype of a function that accepts an array • int func1(int []); • int func1(int x[]); • int func1(int *x); } Almost equivalent, only difference is the first does not specify variable name
Sample Program #include <stdio.h> void changeInt(int *); int main( void ) { int *ptr = NULL, var = 0; ptr = &var; changeInt(ptr); printf("The variable ptr is pointing to: %d", *ptr); return 0; } void changeInt(int * argPtr) { *argPtr = 11; }
Characters, strings, and an introduction to dynamic memory allocation
Strings • arrays of characters • char string[10]; • string: array of characters ending with the null character • null character: ‘\0’ • To store ‘Computer’ in a string, need an array of 9 characters (8 for the letters, one for the null character)
String Initialization • Strings can be initialized many ways: • char string1[10] = “Hello”; • char string2[6] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘\0’}; • char string3[] = “Hi”; • What is the output of the following? • printf(“%d %d %d”, sizeof(string1), sizeof(string2), sizeof(string3); • Answer: • 10 6 3
String / Pointer Relationship • Recall: Array name is a pointer to the first element in the array • Character array is a pointer to the first element in an array • i.e. the beginning of the string • ‘\0’ indicates the end of the string • Array size is incidental • Array name, and ‘\0’ give us all the information we need
Allocating Strings • Strings can be allocated without actually declaring an array • Only the pointer to the first character and the ‘\0’ is needed • Example: • char * msg = “Hello”; is equivalent to: • char msg[] = “Hello”;
Dynamic Allocation of Strings • Dynamic memory allocation • allocating memory ‘on the fly’ • memory allocated at program execution time • using the malloc( ) function is one way to do this • Always include <stdlib.h> • Example: • char *ptr = NULL; • ptr = malloc(5);
malloc( ) function • returns an address • pointer to type void • can store any of C’s data types • accepts an integer parameter • allows for more efficient memory usage
Possible errors with malloc( ) • If there is not enough memory for malloc( ) to complete the request, malloc( ) returns null • Return value should ALWAYS be checked
#include <stdio.h> #include <stdlib.h> int main( void ) { char *ptr = NULL; ptr = malloc(10); if (ptr = = NULL) printf("Memory not allocated"); else printf("Successful allocation of memory"); return 0; } Sample code using malloc( )
Sample code using malloc( ) • #include <stdio.h> • #include <stdlib.h> • int main( void ) { • char *ptr = NULL; • if ((ptr = malloc(10)) = = NULL) • printf("Memory not allocated"); • else • printf("Successful allocation of memory"); • return 0; • }
Sample code using malloc( )Structured example • #include <stdio.h> • #include <stdlib.h> • int main( void ) { • char *ptr = NULL; • if ((ptr = (char *)malloc(10 * sizeof(char))) = = NULL) { • printf("Memory not allocated"); • exit(1); • } • //Code continues from this point • return 0; • }
Displaying Strings - puts( ) • puts( ) accepts a pointer to a string • string literal evaluates as a pointer to a string • prints the string to the screen • automatically inserts new line character at end of string • Example: • char * name = “CSCI 131”; • puts(name); • puts(“this is a string literal”);
Displaying Strings - printf( ) • %s is the string conversion specifier • Example: • char * ptr = "Hello"; • printf("%s", ptr); • printf("%s\n%s", ptr, "there");
Accepting strings from keyboard • Two options • gets( ) • scanf( )
Accepting strings - gets( ) • Reads all characters up to first new line • Discards new line, adds ‘\0’ to end • Returns value as a string (ptr to type char)
Accepting strings - gets( ) • Example: • #include <stdio.h> • int main( void ) { • char name[15]; • printf(“Enter your name\n”); • gets(name); • }
Accepting strings - scanf( ) • Reads all characters up to first occurrence of whitespace • Adds ‘\0’ to end • Returns value as a string (ptr to type char)
Accepting strings - scanf( ) • Sample code: • puts(“Enter your name”) • scanf(“%s”, x);
Can scan a specific number of characters • Sample code (scans first 3 characters): • puts(“Enter your name”) • scanf(“%3s”, x);
gets( ) verses scanf( ) • gets( ) is good when entering text • scanf( ) is useful when entering text and numeric values, or just numeric values
Memory management and more advanced dynamic memory allocation
Type Casting • Consider the following code: • #include <stdio.h> • int main( void ) { • int i = 3, j = 2; • float z = 0.0; • z = i / j; • printf("%f", z); • } • Output: 1.000000
Type Casting • Solving the problem on the previous slide: • #include <stdio.h> • int main( void ) { • int i = 3, j = 2; • float z = 0.0; • z = (float)i / (float)j; //Typecast the i and j to floats • printf("%f", z); • } • Output: 1.500000
Casting Pointers • #include <stdio.h> • int main( void ) { • void * x = NULL; • int p = 3; • (int *)x = &p; //Type casting the void pointer to a • //integer pointer • printf("%d", *(int *)x); //Type casting and dereferencing • return 0; • }
Memory Allocation • Static allocation • explicitly allocating memory in source code • allocation determined at compile time • Dynamic allocation • allocating memory at run time • occurs during program execution
Memory Allocation functionsstdlib.h file • Allocating and freeing memory • malloc( ) • calloc( ) • realloc( ) • free( )