EE108 Section 6 Pointers page 1 of 20 EM108 Software Development for Engineers Section 6 - Pointers 1) Introduction 2) Declaring Pointer Variables 3) Using Pointers 4) Pointer Arithmetic 5) Pointers and Arrays 6) Pointers and Structures 7) Pointers and Functions 8) Common Pointer Pitfalls 9) Complex Example
EE108 Section 6 Pointers page 2 of 20 Pointer: 6.1 Introduction Scalar data type Stores an address of memory Idea: Pointer 65520 Variable 200,000 Examples: pointer to a structured variable Pointer 65400 Variable 65400 1985 65404 John D 65411 53121312 65415 EENG Components: Pointer name Type of item pointed to C uses pointers explicitly with: Arrays Structures Functions
EE108 Section 6 Pointers page 3 of 20 6.2 Declaring Pointer Variables <type> * <pointer_name> ; Notes: Declares the variable <pointer_name> Is a pointer to a memory location of type <type> Allocates memory for the pointer Does not initialise the pointer Components: Pointer name: <pointer_name> = <name> Pointed type: <type> Usage: typedef struct personal_tag { int birth_year; char name [20]; int ID; char school [4]; } personal_type; personal_type* ptr1; int* ptr2; float* ptr3; Note: ptr2 is a pointer to an integer
EE108 Section 6 Pointers page 4 of 20 Example: 6.3 Using Pointers int a; int* ptr_a; float b; float* ptr_b; a = 100; b = 500.0; ptr_a = &a; ptr_b = &b; printf( %d, &a); printf( %d, ptr_a); printf( %d, &b); printf( %d, ptr_b); printf( %d, a); printf( %d, *ptr_a); 63250 100 a 63254? ptr_a 63258 500.0 b 63266? ptr_b 63250 63254 100 63250 63258 500.0 b 63266 63258 63250 63250 63258 63258 100 100 a ptr_a ptr_b printf( %5.2f, b); printf( %5.2f, *ptr_b); 500.00 500.00 Note: operator & gives the address of a variable operator * gives the content of an object pointed to by a pointer
EE108 Section 6 Pointers page 5 of 20 Note: 6.4 Pointer Arithmetic The addition and subtraction involving pointers are performed taking into account the size of the type the pointer points to Assuming the declarations: <type>* ptr; int n; The expression: ptr + n Is evaluated as follows: ptr + n * (sizeof(<type>) Example: int* ptr_a; int a; int n; ptr_a = &a; //let assume ptr_a = 20120 n = 5; ptr_a = ptr_a + n; // ptr_a = 20120 + 20
EE108 Section 6 Pointers page 6 of 20
EE108 Section 6 Pointers page 7 of 20 Observation: 6.5 Pointers and Arrays All the items of an array have the same size equal to the size of their type Array elements are arranged in consecutive memory locations int marks[3]; 4B * 3 = 12 B 1 int (4 bytes) 1 int (4 bytes) 1 int (4 bytes) marks[0] marks[1] marks[2] 1000 1004 1008 Consequence: Pointers can be used to access array items Example: int i; int* ptr; 1 int marks[3]; 2 for (i = 0; i < 3; i++) 3 { scanf( %d, &marks[i]); }
EE108 Section 6 Pointers page 8 of 20 ptr = marks; // ptr = &marks[0]; 4 for (i = 0; i < 3; i++) 5 7 9 11 { } printf( %d, *(ptr + i)); 6 8 10 Effect: 1 ptr? 750 5 i=0; (0 < 3)=> true 6 ptr+0 => ptr = 1000 2 marks[0] marks[1] marks[2]??? 1000 1004 1008 ptr marks[0] marks[1] 75 45 1000 1004 3 marks[0] marks[1] marks[2] 75 45 65 1000 1004 1008 marks[2] 65 /* printf */ *(ptr+0) => 75 1008 4 ptr 1000 750 7 i=1; (1 < 3)=> true 8 ptr+1 => ptr = 1004 ptr Note: ptr = marks same as ptr = &marks[0] marks[0] marks[1] marks[2] 75 45 65 1000 1004 1008 *(ptr+2) and marks[2] access the same object! 9 10 /* printf */ *(ptr+1) => 45 i=2; (2 < 3)=> true...
EE108 Section 6 Pointers page 9 of 20 Observation: 6.6 Pointers and Structures Computer allocates a contiguous memory block for storing a structure The allocated memory space is equal to the added size of all the structure s items typedef struct coord_tag { float x; float y; float z; char text[3] } coord_type; struct coord_tag { float x; float y; float z; char text[10] }; Static Memory Space Allocation coord_type point OR struct coord_tag point 4B * 3 +1B*3= 15 B x (float) (4 bytes) y (float) (4 bytes) z (float) (4 bytes) text (string) (3 bytes) point.x point.y point.z point.text 200 204 208 212
EE108 Section 6 Pointers page 10 of 20 Pointer Declaration coord_type* ptr OR struct coord_tag* ptr Pointer Usage ptr = &point; // ptr = 200 ptr->x = 1.0; // (*ptr).x = 1.0; ptr->y = 2.0; ptr->z = 0.0; // scanf( %f, &(ptr->z)); strcpy(ptr->text, Mon ); ptr 200 550 point.x 1.0 200 2.0 204 point.y point.z point.text 0.0 Mon 208 212
EE108 Section 6 Pointers page 11 of 20 Observation: 6.7 Pointers and Functions Function arguments can be passed in two ways - BY-VALUE or - BY-ADDRESS => in the function, the value of the argument can be modified and the new value is maintained after the function has finished Pointers provide the solution: Pass the address of variables to the function int a, b; my_func(&a, &b); Example ( by-address ) Write a function that swaps the values of the two arguments void swap(int* px, int* py) { 1 2 3 } int temp; temp = *px; *px = *py; *py = temp; pointer px 76 2 pointer py 45 1 2 Addr 76 5 45 temp 2 100 New Values 3 5 2 76 45 int a, b; a = 2; b = 5; swap( &a, &b); a b 2 5 76 45
EE108 Section 6 Pointers page 12 of 20 6.8 Common Pointer Pitfalls Uninitialised Pointers Not assigning a pointer to a memory address before using it int *x; *x = 100; WRONG! x is not initialised in the program with a physical location (address) C compiler initialises a pointer (or variable) with a random value when a pointer (or variable) is declared => X points to a random mem. location. We cannot update information from that location THE RIGHT WAY int* x; int y = 20; x=&y; //pointer is initialised with an address *x = 100; //y will be equal with 100 Illegal indirection char* p; *p =(char*)malloc(100); *p = y'; WRONG! Function malloc() allocates memory dynamically (at run time) malloc() returns a pointer to the allocated block of memory if successful or a NULL pointer otherwise.
EE108 Section 6 Pointers page 13 of 20 THE RIGHT WAY p = (char*)malloc(100); If code rectified as above, one problem is if no memory is available and p is NULL. Therefore we cannot assign: *p = y'; A good C program would check for this: p = (char*)malloc(100); if ( p == NULL) { printf( Error: Out of Memory!! ); exit(1); } *p = y'; Omitted * If you want the value of the location to which a pointer p points, you need to use the expression *p and not p int* x; int y = 20; x = &y; WRONG! You are asking C compiler to print the value contained in the pointer x, which is an address of memory, rather than the value contained at that address. printf("here is the value: %d", x);
EE108 Section 6 Pointers page 14 of 20 THE RIGHT WAY int* x; int y = 20; x = &y; printf("here is the value: %d",*x); Omitted & It is just as easy to forget an & as it is to forget a * Example 1: int x = 0; printf("no: "); scanf("%d", x); WRONG! scanf() receives as parameter a pointer (memory address). By forgetting the &, the value of x ( = 0) is passed instead. scanf() stores the number that it read from the keyboard into memory location 0 => this is wrong! THE RIGHT WAY int x = 0; printf("no: "); scanf("%d", &x);
EE108 Section 6 Pointers page 15 of 20 Example 2: void my_func (int* n); WRONG! int x = 0; my_func(x); We are supposed to pass a pointer as an argument to my_func(), and we gave it an integer instead. THE RIGHT WAY void my_func (int* n); int x = 0; my_func(&x); Multiple Pointers Declaration char* c1, c2; WRONG! This does not declare c2 to be char *, but just char. c1 is a pointer. THE RIGHT WAY char *c1, *c2; Note: char* c1; behaves like char *c1; Memory Allocation char *str; strcpy(str, "Harry"); WRONG! It is not enough just to declare the pointer for a mem. location where a string will be stored Storage space must be allocated for the actual string, before storing any information
EE108 Section 6 Pointers page 16 of 20 THE RIGHT WAY char *str; str = (char*)malloc(10); strcpy(str, "Harry"); Operator Precedence What is the value of z? x = 7; y=14; z = x + y * 2 +1 => z = 7 + 14 * 2 + 1 => z = 43? z = 49? z = 36? Convention: Multiplication takes precedence over addition => Correct: z = 36 C Operator Precedence Table E.g. of operators: ( ) [ ]. ++ -- + - = (Assignment) * (dereference) * (multiplication) In order to save remembering the C precedence rules, it is strongly suggested that you always use parentheses to indicate the correct order in which to perform operations. Some examples: the dangers of remembering wrong the src precedence rules Example 1: Copy a string from src to dest 1 0 2 8 0 void mystrcpy(int* dest, int* src, int size) { for (i=0; i<size; i++) 1 0 *dest++ = *src++; } dest Expression *p++ increments p or what it points to? EM108: Software Development for Engineers Last Saved: 25/01/2007
EE108 Section 6 Pointers page 17 of 20 Answer: *p++ increments p *src++ is equal with *(src++) src 1 0 2 8 0 ++ and * have equal precedence, but they associate right-to-left Ex: if src points to the first element then *src++ first returns 1 and then the increment takes effect and the pointer is stepped one element along the array HOW do we increment what p points to? Answer: (*p)++ 1 0 2 8 0 Ex: if src points to the first element then (*src)++ returns value 1 that will be incremented => value 2 src What whould ++*src do? for (i=0; i<size; i++) *dest++ = ++*src; src 1 2 3 4 5 6 0 2 8 0 2 3 4 5 6 dest Answer: ++*src increments the value pointed by src ++*src is equal with ++(*src) NOTE! Make sure that you understand how pointers work and especially how * and & are used with them!
EE108 Section 6 Pointers page 18 of 20 Note: * means indirection (dereference), ++ or -- mean increment; either pre- or post-increment the combinations can be pre- or post-increment of either the pointer or the data it points to, depending on where the brackets are put ++(*p) (*p)++ *(p++) *(++p) pre-increment data pointed to post-increment data pointed to access data via pointer, post-increment pointer access via pointer which has already been incremented Example 2 #include <stdio.h> #include <stdlib.h> void main() { int x, *p; p = &x; /* initialise pointer */ *p = 0; /* set x to zero */ printf("x is %d\n", x); printf("*p is %d\n", *p); *p += 1; /* increment what p points to */ printf("x is %d\n", x); } (*p)++; /* increment what p points to */ printf("x is %d\n", x); exit(exit_success); Output: X is 0 *p is 0 x is 1 x is 2 *p += 1 same as *p = *p + 1 (*p)++ same as *p = *p + 1
EE108 Section 6 Pointers page 19 of 20 int main() { int i,j,k; 6.9. Complex Example Mem. Addr Mem. Addr Mem. Addr i? 500 j? 600 k? 700 int *p, *q, *r; p? 220 q? 230 r? 240 int **s, **t, **u; s? 20 t? 30 u? 40 i = 7; i 7 500 j 23 600 k 30 700 j = 23; k = i + j; p = &k; q = &i; r = p; i 7 500 j 23 600 q 500 120 k 30 700 p 700 220 r 700 320 k 30 31 310 *r = k+1; *p = (*p + *r)* 5; // (31+31)*5 p 700 220 i = *(&j); r 700 320 700 7 23 i 500 s = &q; u = &p; t = s; i q 23 Mem. Addr 500 500 120 Mem. Addr k 310 700 p 700 220 Mem. Addr s 120 20 u 220 40 t 120 30
EE108 Section 6 Pointers page 20 of 20 Mem. Addr p = *t; Mem. Addr k 310 700 p 700 500 220 i 23 500 q 500 120 t 120 30 i 23 529 500 *p = **u * i; // i=i*i p 500 220 u 220 40 **s = i + j + k; //i=i+j+k i 529 862 500 q 500 120 s 120 20 k 310 700 j 23 600 j = 0; j 23 0 600 r = p = &j; i 862 500 p 500 600 220 k 310 700 r 700 600 320 s = &r; t = s; s q 500 120 120 320 20 t 120 320 30 j 0 600 u = &p; p = &k; p u 600 700 220 220 220 40 k 310 700 } **u *= (*p * **s) * (i * j * k); //k=k*(k*j)*(i*j*k) printf("i = %d\n", i); //i = 862 printf("j = %d\n", j); //j = 0 printf("k = %d\n", k); //k = 0 return (EXIT_SUCCESS); k 310 0 700