This page contains examples of pointers. These examples assume the reader has the following knowledge: compiling C programs, variable creation and assignment, arrays, functions, basic I/O and an understanding of computer memory layout. These examples build from simple to more complex.
Basic Pointers
[edit | edit source]Creating, initializing and assigning
[edit | edit source]This example shows simple pointer creation, assignment and dereference.
#include<stdio.h> /*Example showing simple pointer assignment operations. */ intmain(intargc,char*argv[]) { int*intPtr1; int*intPtr2; inta=5; intb=10; printf("\nBefore Initializing pointers."); printf("\nintPtr1: %d, *intPtr1: %d",intPtr1,*intPtr1); printf("\nintPtr2: %d, *intPtr2: %d\n",intPtr2,*intPtr2); /*Initialize the pointers*/ intPtr1=NULL; intPtr2=NULL; printf("\nAfter Initializing pointers to NULL"); printf("\nintPtr1: %d",intPtr1); printf("\nintPtr2: %d\n",intPtr2); intPtr1=&a; intPtr2=&b; printf("\nAfter pointing intPtr1 to the address of 'a' and " "\npointing intPtr2 to the address of 'b'\n"); printf("\nintPtr1: %d, *intPtr1: %d",intPtr1,*intPtr1); printf("\nintPtr2: %d, *intPtr2: %d",intPtr2,*intPtr2); printf("\na: %d, b: %d\n",a,b); *intPtr1=7; *intPtr2=12; printf("\nAfter assigning 7 into the memory location pointed to by " "intPtr1 \n and assigning 12 into the memory location pointed to by intPtr2"); printf("\nintPtr1: %d, *intPtr1: %d",intPtr1,*intPtr1); printf("\nintPtr2: %d, *intPtr2: %d",intPtr2,*intPtr2); printf("\na: %d, b: %d\n",a,b); intPtr1=intPtr2; printf("\nAfter storing the memory location of intPtr2 into intPtr1. \nMakes intPtr2 now point to variable 'b' as well"); printf("\nintPtr1: %d, *intPtr1: %d",intPtr1,*intPtr1); printf("\nintPtr2: %d, *intPtr2: %d",intPtr2,*intPtr2); printf("\na: %d, b: %d\n",a,b); *intPtr2=10; printf("\nAfter assigning '10' into the memory location pointed to by intPtr1 and intPtr2"); printf("\nintPtr1: %d, *intPtr1: %d",intPtr1,*intPtr1); printf("\nintPtr2: %d, *intPtr2: %d",intPtr2,*intPtr2); printf("\na: %d, b: %d\n",a,b); b=25; printf("\nAfter assigning '25' into the variable 'b'"); printf("\nintPtr1: %d, *intPtr1: %d",intPtr1,*intPtr1); printf("\nintPtr2: %d, *intPtr2: %d",intPtr2,*intPtr2); printf("\na: %d, b: %d\n",a,b); }
Pointer as function argument
[edit | edit source]This example shows how pointers can be used in functions. The code gives the reader some questions to consider and answer on their own.
#include<stdio.h> /*Example showing how pointers are used in functions. */ /* Only swaps the values within this fuction */ voidbadSwap(intc,intd); voidgoodSwap(int*c,int*d); voiddecrement(int*p); voidincrement(int*p); voidbadSwap(intc,intd){ inttemp=0; printf("\nbadSwap"); printf("\n\tBefore swapping in badSwap"); printf("\n\ttemp: %d, c: %d, d: %d",temp,c,d); temp=c; c=d; d=temp; // Why won't this work? printf("\n\tAfter swapping in badSwap"); printf("\n\ttemp: %d, c: %d, d: %d",temp,c,d); } /* Swaps the values using pointers*/ voidgoodSwap(int*c,int*d){ inttemp=0; printf("\ngoodSwap"); printf("\n\tBefore swapping in goodSwap"); printf("\n\ttemp: %d, c: %u, *c: %d, d: %u, *d: %d",temp,c,*c,d,*d); temp=*c; *c=*d; *d=temp; // Why does this work? printf("\n\tAfter swapping in goodSwap"); printf("\n\ttemp: %u, c: %u, *c: %d, d: %u, *d: %d",temp,c,*c,d,*d); } voidbadSwap2(int*c,int*d){ int*temp=NULL; printf("\nbadSwap2"); printf("\n\tBefore swapping in badSwap2"); printf("\n\ttemp: %d, c: %u, *c: %d, d: %u, *d: %d",temp,c,*c,d,*d); temp=c; c=d; d=temp; // c and d have changed values! Great! Why won't their values be changed when // we return? printf("\n\tAfter swapping in badSwap2"); printf("\n\ttemp: %u, c: %u, *c: %d, d: %u, *d: %d",temp,c,*c,d,*d); } /*Decrements the value pointed to by p */ voiddecrement(int*p){ // What we want *p = *p - 1; (*p)--; // What does *p-- do? } /*Increments the value pointed to by p*/ voidincrement(int*p){ inttemp=p; // What we want *p = *p + 1 (*p)++; // What does *p++ do? printf("\nincrement"); printf("\n\t p: %u, *p: %u, &p: %u\n",p,*p,&p); p=p+1; printf("\n\t p: %u, *p: %u, &p: %u\n",p,*p,&p); p=temp; p=*p+1; printf("\n\t p: %u, &p: %u\n",p,&p); p=temp; p=&p+1; printf("\n\t p: %u, *p: %u, &p: %u\n",p,*p,&p); p=temp; *p=p+1; printf("\n\t p: %u, *p: %u, &p: %u\n",p,*p,&p); p=temp; *p=&p+1; printf("\n\t p: %u, *p: %u, &p: %u\n",p,*p,&p); p=temp; } intmain(intargc,char*argv[]){ int*aPtr; int*bPtr; inta=5; intb=10; /*Initialize the pointers*/ aPtr=&a; bPtr=&b; /*Before call to badSwap*/ printf("\nBefore call to badSwap"); printf("\n\taPtr: %u, *aPtr: %d",aPtr,*aPtr); printf("\n\tbPtr: %u, *bPtr: %d",bPtr,*bPtr); printf("\n\ta: %d, b: %d\n",a,b); badSwap(a,b); /* After call to badSwap */ printf("\n\nAfter call to badSwap"); printf("\n\taPtr: %u, *aPtr: %d",aPtr,*aPtr); printf("\n\tbPtr: %u, *bPtr: %d",bPtr,*bPtr); printf("\n\ta: %d, b: %d\n",a,b); /*Before call to goodSwap*/ printf("\nBefore call to goodSwap"); printf("\n\taPtr: %u, *aPtr: %d",aPtr,*aPtr); printf("\n\tbPtr: %u, *bPtr: %d",bPtr,*bPtr); printf("\n\ta: %d, b: %d\n",a,b); goodSwap(aPtr,bPtr); goodSwap(&a,&b); /* After call to goodSwap */ printf("\n\nAfter call to goodSwap"); printf("\n\taPtr: %u, *aPtr: %d",aPtr,*aPtr); printf("\n\tbPtr: %u, *bPtr: %d",bPtr,*bPtr); printf("\n\ta: %d, b: %d\n",a,b); badSwap2(aPtr,bPtr); /* After call to badSwap2*/ printf("\n\nAfter call to badSwap2"); printf("\n\taPtr: %u, *aPtr: %d",aPtr,*aPtr); printf("\n\tbPtr: %u, *bPtr: %d",bPtr,*bPtr); printf("\n\ta: %d, b: %d\n",a,b); increment(&a); return0; }
Advanced Pointers
[edit | edit source]This section describes how to use pointers to access dynamically allocated memory, point to structures, point to other pointers, point to functions, and point to void.
Pointers with Malloc
[edit | edit source]This example show how pointers can be used with malloc to point to blocks of memory.
#include<stdlib.h> #include<stdio.h> #define NUM_ALPHA 26 typedefunsignedcharuchar; typedefunsignedintuint; /* * Fills the data pointed to by cPtr with the alphabet. */ voidfillWithAlpha(uchar*cPtr,intsize); voidprintDataAsChar(uchar*cPtr,intsize); /* This function shows how to malloc data. It shows that data might * be zero upon initialization, but it is not guaranteed to be 0. * */ voidmallocExample(); /* This function shows malloc data can be passed to a function. */ voidmallocWithFunction(); intmain(intargc,char**argv){ mallocExample(); mallocWithFunction(); return0; } voidmallocExample(){ /* Using malloc */ uintsize,i; printf("\n Enter the desired size: "); scanf("%d",&size); uchar*data; /* Check to make sure a NULL pointer wasn't returned from malloc */ if((data=(uchar*)malloc(size))==NULL) exit(1); /* Raw data after first malloc. Not guaranteed to be initialized*/ printf("\n After first malloc"); for(i=0;i<size;i++) printf("\n [%d]: %d",i,data[i]); /* Fill */ for(i=0;i<size;i++) data[i]=i; /* After fill */ printf("\n After fill"); for(i=0;i<size;i++) printf("\n [%d]: %d",i,data[i]); /* When data is no longer needed it MUST be freed */ free(data); if((data=(uchar*)malloc(size))==NULL) exit(1); /* Raw data after second malloc. Shows how there can be stuff 'left over' * in memory after malloc call*/ printf("\n Raw data after malloc"); for(i=0;i<size;i++) printf("\n [%d]: %d",i,data[i]); free(data); } voidmallocWithFunction(){ uintsize; printf("\n Enter the desired size: "); scanf("%d",&size); uchar*data; if((data=(uchar*)malloc(size))==NULL) exit(1); printDataAsChar(data,size); fillWithAlpha(data,size); printDataAsChar(data,size); } voidfillWithAlpha(uchar*cPtr,intsize){ inti; for(i=0;i<size;i++) cPtr[i]='a'+i%NUM_ALPHA; } voidprintDataAsChar(uchar*cPtr,intsize){ inti; for(i=0;i<size;i++) printf("[%d]: %c \n",i,cPtr[i]); }
Pointers to structs
[edit | edit source]Below is example showing how pointers are used with structures. It creates a classic link list which stores numbers in sorted form.
#include<stdio.h> #include<stdlib.h> /* Example showing how pointers are used with structures. */ structLinkList { intNumber; structLinkList*Next; } insertLinkList(structLinkList**ll,intNumber) { structLinkList*llTemp,*llSearch,*llPrev; intlastElementFlag=0; llTemp=(structLinkList*)malloc(sizeof(structLinkList)); llTemp->Number=Number; llTemp->Next=NULL; if(*ll==NULL) /* LinkList is empty */ *ll=llTemp; elseif((*ll)->Number>Number) {/*insert first element */ llTemp->Next=*ll; *ll=llTemp; } else{ llSearch=*ll; while(llSearch->Number<Number) { if(llSearch->Next==NULL) { lastElementFlag=1; break; } llPrev=llSearch; llSearch=llSearch->Next; } if(llSearch->Number==Number) printf("Number %d already exists\n",Number); elseif(lastElementFlag==1) /* Insert last element */ { llSearch->Next=llTemp; } else /* Insert between */ { llPrev->Next=llTemp; llTemp->Next=llSearch; } } } printLinkList(structLinkList**ll) { structLinkList*llTemp; llTemp=*ll; while(llTemp!=NULL) { printf("Address is %d and Number is %d \n",llTemp->Next,llTemp->Number); llTemp=llTemp->Next; } } main() { structLinkList*llist=NULL,*llist2=NULL; printf("Inserting 4\n"); insertLinkList(&llist,4); printf("Inserting 1\n"); insertLinkList(&llist,1); printf("Inserting 5\n"); insertLinkList(&llist,5); printf("Inserting 9\n"); insertLinkList(&llist,9); printf("Inserting 2\n"); insertLinkList(&llist,2); printf("Inserting 9\n"); insertLinkList(&llist,9); printf("Inserting 1\n"); insertLinkList(&llist,1); printf("Inserting 5\n"); insertLinkList(&llist,5); printf("Inserting 4\n"); insertLinkList(&llist2,14); printf("Inserting 1\n"); insertLinkList(&llist2,17); printf("Printing llist \n"); printLinkList(&llist); printf("Printing llist2 \n"); printLinkList(&llist2); }
Double pointer
[edit | edit source]TODO
Void pointer
[edit | edit source]
A pointer of type void (e.g void *pointerName) represents the address of an object, but not its type, i.e it points to a variable that can be of any type. With void*, you can cast the type of this pointer to any other type.
#include<stdio.h> intmain(){ inta=12; void*pointer=&a; printf("Value *(int *)pointer is: %d \n",*(int*)pointer);//12 printf("Value (int *)pointer is: %p \n",(int*)pointer);//0x7fff1f05ed4c printf("Value pointer is: %p \n",pointer);//0x7fff1f05ed4c }
Or void pointer can be defined in that way:
void*pointer; inta=0; pointer=&a;
Pointer Arithmetic
[edit | edit source]TODO Pointers and Arrays; Pointer Arithmetic [This section corresponds to K&R Sec. 5.3]
Pointers do not have to point to single variables. They can also point at the cells of an array. For example, we can write
int *ip; int a[10]; ip = &a[3];
and we would end up with ip pointing at the fourth cell of the array a (remember, arrays are 0-based, so a[0] is the first cell). We could illustrate the situation like this:
We'd use this ip just like the one in the previous section: *ip gives us what ip points to, which in this case will be the value in a[3].
Once we have a pointer pointing into an array, we can start doing pointer arithmetic. Given that ip is a pointer to a[3], we can add 1 to ip:
ip + 1
What does it mean to add one to a pointer? In C, it gives a pointer to the cell one farther on, which in this case is a[4]. To make this clear, let's assign this new pointer to another pointer variable: ip2 = ip + 1;
Now the picture looks like this:
If we now do *ip2 = 4;
we've set a[4] to 4. But it's not necessary to assign a new pointer value to a pointer variable in order to use it; we could also compute a new pointer value and use it immediately: *(ip + 1) = 5;
In this last example, we've changed a[4] again, setting it to 5. The parentheses are needed because the unary contents of operator * has higher precedence (i.e., binds more tightly than) the addition operator. If we wrote *ip + 1, without the parentheses, we'd be fetching the value pointed to by ip, and adding 1 to that value. The expression *(ip + 1), on the other hand, accesses the value one past the one pointed to by ip.
Given that we can add 1 to a pointer, it's not surprising that we can add and subtract other numbers as well. If ip still points to a[3], then
*(ip + 3) = 7;
sets a[6] to 7, and *(ip - 2) = 4;
sets a[1] to 4.
Up above, we added 1 to ip and assigned the new pointer to ip2, but there's no reason we can't add one to a pointer, and change the same pointer:
ip = ip + 1;
Now ip points one past where it used to (to a[4], if we hadn't changed it in the meantime). The shortcuts we learned in a previous chapter all work for pointers, too: we could also increment a pointer using ip += 1;
or ip++;
Of course, pointers are not limited to ints. It's quite common to use pointers to other types, especially char. Here is the innards of the mystrcmp function we saw in a previous chapter, rewritten to use pointers. (mystrcmp, you may recall, compares two strings, character by character.)
char *p1 = &str1[0], *p2 = &str2[0];
while(1) { if(*p1 != *p2) return *p1 - *p2; if(*p1 == '\0' || *p2 == '\0') return 0; p1++; p2++; }
The autoincrement operator ++ (like its companion, --) makes it easy to do two things at once. We've seen idioms like a[i++] which accesses a[i] and simultaneously increments i, leaving it referencing the next cell of the array a. We can do the same thing with pointers: an expression like *ip++ lets us access what ip points to, while simultaneously incrementing ip so that it points to the next element. The preincrement form works, too: *++ip increments ip, then accesses what it points to. Similarly, we can use notations like *ip-- and *--ip.
As another example, here is the strcpy (string copy) loop from a previous chapter, rewritten to use pointers:
char *dp = &dest[0], *sp = &src[0]; while(*sp != '\0') *dp++ = *sp++; *dp = '\0';
(One question that comes up is whether the expression *p++ increments p or what it points to. The answer is that it increments p. To increment what p points to, you can use (*p)++.)
Advanced Pointers with Arrays
[edit | edit source]Shows how arrays and pointers can be treated the same. Example: Creating an array structure with pointers. Example: Using pointer arithmetic to index array
Using Pointers to Traverse an Array
[edit | edit source]#include<stdio.h> intmain(){ /* Create array */ intarr[10]; /* Fill with data */ for(inti=0;i<10;i++){ arr[i]=i*5; } /* Create pointer to first item */ int*ptr=&arr[0]; /* Iterate through items */ for(inti=0;i<sizeof(arr)/sizeof(int);i++){ /* Print the address and the value */ printf("%p: %d\n",ptr,*ptr); /* Increment pointer by sizeof(int) */ ptr++; } return0; } /* OUTPUT 0x7fff69a4fa20: 0 0x7fff69a4fa24: 5 0x7fff69a4fa28: 10 0x7fff69a4fa2c: 15 0x7fff69a4fa30: 20 0x7fff69a4fa34: 25 0x7fff69a4fa38: 30 0x7fff69a4fa3c: 35 0x7fff69a4fa40: 40 0x7fff69a4fa44: 45 */
Passing arrays to functions using pointers
[edit | edit source]#include<stdio.h> voidprint(int*arr,intp){ for(inti=0;i<p;i++){ printf("%p: %d\n",arr,*arr); arr++; } } voidmultiply(int*arr,intp){ for(inti=0;i<p;i++){ *arr*=5; arr++; } } intmain(){ intarr[10]; for(inti=0;i<10;i++){ arr[i]=i; } printf("Before modification: \n"); print(&arr[0],sizeof(arr)/sizeof(int)); multiply(&arr[0],sizeof(arr)/sizeof(int)); printf("\nAfter modification: \n"); print(&arr[0],sizeof(arr)/sizeof(int)); return0; } /* OUTPUT Before modification: 0x7fff63f0aa40: 0 0x7fff63f0aa44: 1 0x7fff63f0aa48: 2 0x7fff63f0aa4c: 3 0x7fff63f0aa50: 4 0x7fff63f0aa54: 5 0x7fff63f0aa58: 6 0x7fff63f0aa5c: 7 0x7fff63f0aa60: 8 0x7fff63f0aa64: 9 After modification: 0x7fff63f0aa40: 0 0x7fff63f0aa44: 5 0x7fff63f0aa48: 10 0x7fff63f0aa4c: 15 0x7fff63f0aa50: 20 0x7fff63f0aa54: 25 0x7fff63f0aa58: 30 0x7fff63f0aa5c: 35 0x7fff63f0aa60: 40 */
