Pointers to structs

1 / 11

# Pointers to structs

## Pointers to structs

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -
##### Presentation Transcript

1. Pointers to structs

2. Pointers to structs • A pointer to a struct is used in the same way as a pointer to a simple type, such as an int. Pointers to structs were introduced previously in the context of passing the address of a struct as a function argument in order to allow the function to change the values of the members of the struct. • Sometimes we wish to pass a pointer to a struct as a function argument even though we do not wish to change the values of any of its members. This need may arise because of the large overhead involved in "bodily" copying the values of all of the members of the struct. It may be much more efficient to pass the address of the struct and to de-reference the pointer within the function, using the usual indirection operator *.

3. As an example, consider a variation on the function show_details(). We had specified the type PERSON, using the following typedef:- typedef struct {int age;float weight;} PERSON; And the original version of show_details() was:- void show_details( PERSON who ){printf( "Person's age was: %d\n", who.age );printf( " sex was: %c\n", who.sex );who.weight = who.weight * 2.2;/* Kg -> lb */printf( " weight (lb) was: %5.1f\n", who.weight );}

4. Let us define a new function s2_details() which takes an argument of type PERSON * - the address of a PERSON. void s2_details( PERSON * pWho ){printf( "Person's age was: %d\n", (*pWho).age );printf( " sex was: %c\n", (*pWho).sex );/* Kg -> lb */(*pWho).weight = (*pWho).weight * 2.2;printf( " weight (lb) was: %5.1f\n", (*pWho).weight );} • pWho holds the address of a whole struct, *pWho denotes the struct itself, and (*pWho).age denotes one of its members. • So s2_details() can access all the members of a PERSON without having to copy the whole struct.

5. The Arrow Operator -> • C provides a more friendly syntax for accessing the members of a structure from a pointer, using the -> operator. For example, • pWho->age is the same as (*pWho).age. • (In general, the -> operator returns the member named on the right of -> from the structure pointed to by the pointer on the left.) • So we could simplify the assignment statement within s2_details() as follows

6. (*pWho).weight = (*pWho).weight * 2.2; would become pWho->weight = pWho->weight * 2.2;

7. Pointers to Constants (ANSI only) • The problem with passing a pointer as a function argument is that the function has total freedom to change the object pointed at. In the above example, the programmer has needlessly changed the value of the .weight member. Instead of just displaying a weight, the function changes its value. • There is one safeguard which can allow a programmer to pass a pointer to a function knowing that the function will not be allowed to alter it - declare the argument as constant, using the const keyword. • In the new definition of s2_details(), below, pWho is declared as a pointer to a const PERSON. Any statement which attempted to change the value of the structure pointed at by pWho would be flagged as a compilation error.

8. void s2_details( const PERSON * pWho ){printf( "Person's age was: %d\n", pWho->age );printf( " sex was: %c\n", pWho->sex );printf( " weight (lb) was: %5.1f\n", pWho->weight * 2.2 );} • Note that we have eliminated the assignment statement • pWho->weight = pWho->weight * 2.2; • and replaced it by using the expression pWho->weight * 2.2 inside the printf() statement.

9. Dynamic Memory Allocation - the Heap • C provides a managed area of storage known as the heapwhich is available to the programmer for the creation of data objects of any size while the program is actually executing. Why would we wish to use the heap? • We have seen that one problem with arrays is that the dimension must be declared at compile time: • to be on the safe side, the programmer must make the array large enough for any conceivable case. • Another problem with arrays is the very simplicity of their structure. There are some data structures, e.g. trees, which do not naturally fit into a uniform collection of adjacent elements each of the same size. • A further problem with arrays is that the addresses of all their elements are fixed. Some data objects have a tendency frequently to change their structure as a program executes: if such an object is stored in an array then there will be much copying of elements to fill up the "holes" which appear.

10. There are two standard library functions malloc() and free() which allow the programmer to claim space from the heap and, subsequently, to release it. The prototypes for these functions are in the include file stdlib.h. • malloc() needs to know how much space is required. It locates that amount of space within the heap, marks it as "in use" and returns a pointer to it. • For example, malloc( sizeof( float ) ) would claim space on the heap to store one float. In order to access this float we need to have declared a pointer ( a float * ) which will hold its address

11. #include<stdio.h>#include<stdlib.h> void main(){float * pZ; pZ = malloc( sizeof( float ) ); *pZ = 12.3; printf( "Address is %u and contents are %f\n", pZ, *pZ );} In practice if we wished to store a value of type float then we would simply declare a float variable. We are more likely to use the heap if we wish to store an unknown number of structured types. For example to store a PERSON we could have PERSON * pWho = malloc( sizeof( PERSON ) ); Here we have declared pWho as a pointer to PERSON and we have also initialised it by a call of malloc(). The storage pointed to by pWho could be written to by assignment statements such as /* or (*pWho).age = 40 */pWho->age = 40;pWho->sex = 'M';pWho->weight = 75.2;