Download presentation
Presentation is loading. Please wait.
Published byCandace Wade Modified over 9 years ago
1
Pointer definitions, usage, operations, arrays of pointers, function pointers Referencing addresses, Pointers
2
The Pointer Concept and Usage in C Concept of Pointer as memory address Pointer definitions Usage of pointers Operations on pointers Function arguments: Call by Value/Reference Arrays of pointers and Pointer types of Functions The const qualifier Pointers to Functions
3
Concept of Pointer as memory address All programs exist in RAM when executing Data and Code Variables and data structures (eg. arrays) are allocated memory locations (addresses) In static blocks, in stack frames, on the heap It is often useful to exploit knowledge of data structures along with location, or address, data It is the ability to define a variable that stores address values, coupled with the ability to indirectly access meaningful data values, that makes pointers useful.
4
Concept of Pointer as memory address For program codes produced by a compiler, RAM is partitioned into blocks of memory according to what kind of data is placed in the blocks Executable instructions (code) Data Stacks Heaps Buffers For programmer defined variables, names are used int intVarname = 64 ; float fltVarName = 3.14159 ; Although we usually think of the value stored in a variable, the variable name actually refers to a RAM address (at which the value is stored) However, the names of scalar variables do not correspond directly to their address location values intVarname does not have a value ! CODE DATA BUFFERS STACKS HEAP Code Block Address Data Block Address Heap Block Address Stack Block Address Buffer Block Address intVarname fltVarname 64 3.14159
5
Pointer definitions C defines two pointer related operators * - dereferencing (asterisk) & - address_of (ampersand) Examples: // Variable name for an integer storage with value 5 int Varname = 5 ; /* Variable name for a pointer-to-integer storage with value set to the RAM address of Varname */ int * ptrVarname = &Varname ; The strongly typed nature of the C language dictates that all pointers must be type-specific. Each pointer variable is said to point to a RAM address where it is expected that data of a compatible type is stored. Any type incompatibility will be reported as a compiler error.
6
Usage of pointers Declarations int N, *ptrN ; // N is an int variable, ptrN is pointer double * X, * Y ; // Must always use * for each pointer Assigning values ptrN = &N ; // Use the address-of operator to get the RAM address X = Y ; // Can assign type compatible pointers *X = 24.53 ; /* Use dereferencing to assign compatible values that will be stored at the RAM location X is pointing to */ *Y = *X ; /* Copy the value stored where X is pointing to where Y is pointing */ WARNING! Be careful to separate the notion of data value from memory address Variables that hold meaningful data provide direct access to RAM Pointers that hold address data provide indirect access to RAM when dereferencing them to get at meaningful data
7
Usage of pointers There is a special constant that deserves emphasis – NULL If a pointer variable is not assigned a value then it cannot referenced. It is useful to have a value that can be referenced, but which indicates no particular value of the address int * ptr = NULL ; This provides advantages in programming logic because one can test the value of a pointer if ( ptr != NULL ) { /* perform logic */ } We will see much more use of NULL pointers in future discussion of dynamic linked lists and other advanced data structures
8
Operations on pointers The following operations are meaningful for pointers and define pointer arithmetic Assume the declarations: int aN [100] ; char aC [256] ; double aD [ 1000 ] ; int * pN ; char * pC ; double * pD ; The following are valid statements: pN = aN ; pC = aC ; pD = aD ; // Array names are pointers !! pN = &aN[0] ; pC = &aC[0] ; pD = &aD[0] ; // Equivalent to above pN = pN + 1 ; // Points to aN[1] pN++ ; ++pN ; // …. and then to aN[2], then aN[3] pN -= 3 ; // …. and now back to aN[0] Note above that we have used +, -=, and ++ All arithmetic operations on pointers must involve integer addition or subtraction only !
9
Operations on pointers Pointers are often used with arrays. Assume the following: float A[1000], * ptrA = &A[0], * ptrB = &A[49] ; Consider the following equivalent statements A[5] = 6.73 ; ptrA[5] = 6.73 ; *(ptrA+5) = 6.73 ; Now consider a problem. Using pointer arithmetic only, determine the array subscript corresponding to the position of the pointer relative to the beginning of the array: Assume: int Subscript ; Answer: Subscript = ( ptrB – ptrA ) / sizeof( float ) ; // the value above is 49 Note that pointers can be subtracted from each other, but not added! If A, B, C and D are compatible pointers, then consider the expressions: A – B OKA + B ERR A – B + COKA + B – CERR A – B + C – D OKA + (B - C) OK (A – B) + (C – D) OK A – B – D + C ERR
10
Arrays of pointers Problem: Sort a 2D array in ascending order on first column: double X[1000][50000] ; Note that the size of the rows is immense so exchanging rows will take a lot of processing time Answer: Use an array of pointers: double * pX[1000], * tptr ; Initialize each element to point to the beginning of each row for( k=0; k<50000; k++ ) pX[k] = &X[k][0] ; for( i=0; i 0 ; j-- ) if( *(pX[j])<*(pX[j-1]) ) { tptr = pX[j] ; pX[j] = pX[j-1] ; pX[j-1] = tptr ; } It is important to note that in this example the actual values stored in X never move position (ie. undergo rearrangement). We could obtain row output (on a suitably wide terminal) as follows: for( k=0 ; k<1000 ; k++ ) { for( j=0 ; j < 50000 ; j++ ) printf( “%10.2lf”, *( pX[k] + j ) ) ; printf( “\n” ) ; } Note that pX[k] points to the beginning of a particular row in the orginal array X, while pX[k]+j points to the j’th element in that row. It is the full expression *( pX[k] + j ) that actually accesses (ie. dereferences) the meaningful double values in X.
11
Function arguments: Call by Value/Reference There are two mechanisms for passing data to a function through the arguments Call by Value When the argument is the name of a variable int vCube( int x ) { return x*x*x ; } Note that vCube returns the value computed and leaves it to the programmer to write a statement that accepts the value Y = vCube( 25 ) ; Call by Reference When the argument is a pointer variable void rCube( int * X ) { *X = *X * *X * *X ; return ; } For rCube() the result computed is placed back into the storage used to input the original value rCube( &Y ) ; // result is placed back into Y This approach can save both unnecessary memory allocations (on the stack) and also memory transfers of data (during marshalling of the function call). An important point !! In C, the separation of argument passing mechanisms into Call-by-Value versus Call-by-Reference is just an illusion, a conceptual device that may be useful for some programmers. In actuality, C (and all other languages) uses Pass-by-Value (aka Call-by-Value) exclusively and explicitly in all cases of argument passing. Remember that passing a pointer is still passing a value – the programming approach just exploits this kind of address data appropriate to the logic requirements (eg. access to arrays, pointer arithmetic, dereferencing).
12
Pointer types of Functions Functions must have data types declared. Pointers are just another data type, so functions can be declared as being of type pointer double * Larger( double X, double Y ) { if( X > Y ) return &X ; else return &Y ; } Larger() has type double *, hence its return values must be compatible data types (eg. &X, &Y) Assuming double U=10.34, W=82.754, Z ; one can use this function to access the result Z = *(Larger(U,W)) ; Be careful to differentiate between return values that are pointers (addresses in RAM) versus data (meaningful values).
13
The const qualifier The notion of a constant value is very different than that of a varying value, hence variable. When a program runs, storages can be allocated to handle values that are expected to vary, while protecting those that must not change. Example: const float Pi = 3.141592 ; float Area, R=22.4 ; Area = Pi * R * R ; // This is quite acceptable Pi = R ; // Compiler ERROR ! Now we consider applying const to pointers, which themselves may point to const or non-const references.
14
The const qualifier With pointers there are four kinds of patterns to consider. non-const pointer to non-const data non-const pointer to const data const pointer to non-const data const pointer to const data Considering that the purpose of const, from a software engineering perspective, is to provide protection (hence security) for data, each of these patterns must be carefully examined and understood This is true whether a pointer value, or a data value These will be illustrated through examples in the following slides.
15
The const qualifier When both the pointer, and the data to which it points, are intended to be modified non-const pointer to non-const data Example: Assume: int N = 5, A[5] = {1,2,3,4,5} ; Function: void Add1 ( int * B, int n ) { for( ; n>0 ; n--, B++ ) (*B)++ ; return ; } Note that both the pointer B, and the array values (in A) are modified during the call: Add1( A, N ) ;
16
The const qualifier When the pointer to data is intended to be modified, but the data to which it points must not be modified non-const pointer to const data Example Assume: int N; const char A[5] = {‘M’,’e’,’s’,’s’,’a’,’g’,’e’,’\0’} ; Function: int StrLen ( const char * S ) { int n = 0 ; for( ; *S != ‘\0’ ; S++ ) n++ ; return n ; } Note that the pointer S is modified, but the values in the string A are not modified in the call: N = StrLen( A ) ; Any attempt to modify data in A results in a compiler error.
17
The const qualifier When the pointer to data must not be modified, but the data to which it points may be modified const pointer to non-const data Example Assume: float Pi = 3.14159, * const ptrPi = &Pi ; Function: void ChangePi ( float * const P ) { const float Q = 3.14 ; *P = 3.1415 ; P = &Q ; // Compiler error ! return ; } Note that the value of Pi may change, but the pointer P may not be modified to point at Q in the call: ChangePi( ptrPi ) ; Also note that all array names represent const pointers.
18
The const qualifier When neither the pointer to data, or the data to which it points, may be modified const pointer to const data This technique is used to promote maximum protection over data and references to data Example: int main ( ) { int N = 3, * ptrN = &N ; const int X = 5, * const ptrX = &X ; *ptrX = 3 ; // Compiler error ptrX = &N ; // Compiler error ptrX = ptrN ; // Compiler error } Always think about data protection when using const.
19
Pointers to Functions Since function codes and data occupy memory during program execution, it makes sense that we could refer to the locations of the code, or data. When referring to data we may use and possibly modify the data When referring to code, however, one must never modify the code data (unpredictable side effects) This leads to the notion of a pointer to a function Example prototypes: void Bubble( int A[ ], const int N, int (*compare)( int x, int y ) ) ; or void Bubble( int [ ], const int, int (*)( int, int ) ) ;
20
Pointers to Functions Example function definitions: void Bubble( int A[ ], const int N, int (*compare)( int x, int y ) ) { int p, q ; for( p=1 ; p<N ; p++ ) for( q=0 ; q<N-1 ; q++ ) if( (*compare)( A[q], A[q+1] ) ) swap( &A[q], &A[w+1] ) ; return ; } int ascending( int a, int b ) { return a > b ; } int descending( int a, int b ) { return a < b ; } Example of usage: Bubble( Arr1, N1, ascending ) ; Bubble( Arr2, N2, descending ) ; Study the examples in the textbook.
21
A Cautionary Note Pointers open up an entirely new abstraction for programming, but one which requires deeper knowledge and awareness of memory architectures and data structures Pointers are used more for optimality of performance by reducing the complexity of memory addressing and access to data Although using pointers can be elegantly expressed, it takes experience to understand how to achieve elegance A solid understanding of pointers will lead to easier appreciation of abstract data types (ADT) and container based algorithms.
22
Summary Concept of Pointer as memory address Pointer definitions Usage of pointers Operations on pointers Arrays of pointers Function pointers
23
Topic Summary Pointer Concepts & Mechanisms Address of :: & Dereferencing :: * Operations and Arithmetic Connection to arrays, functions and data structures Function pointers Reading – Chapter 7 Pointers
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.