Anybody who is working on Linux environment (not ust deve!o"ers#, shou!d understand the $undamenta!s o$ % "rogramming !anguage and write some basic % "rogram& 'his artic!e is "art o$ our ongoing series on % "rogramming !anguage& 'he conce"t o$ "ointers is one o$ the most "ower$u! $undamenta!s o$ %(%)) !anguage& 'hrough "ointers a deve!o"er can direct!y access memory $rom his(her code which makes memory re!ated o"erations very $ast& *ut, as a!ways, with great "ower comes great res"onsibi!ity& A deve!o"er has to very care$u!!y make use o$ "ointers in order to avoid some "rob!ems that can be nightmare to debug& +n this artic!e we wi!! study the very basic conce"t o$ "ointers with exam"!es in % !anguage&
A norma! variab!e 0var1 has a memory address o$ 1001 and ho!ds a va!ue 50& A pointer variable has its own address 2023 but stores 1001, which is the address o$ the variab!e 0var1
+n the above dec!aration / 1& "ointer4ty"e / +t s"eci$ies the ty"e o$ "ointer& +t can be int,char, $!oat etc& 'his ty"e s"eci$ies the ty"e o$ variab!e whose address this "ointer can store& 2& "ointer4name / +t can be any name s"eci$ied by the user& 5ro$essiona!!y, there are some coding sty!es which every code $o!!ows& 'he "ointer names common!y start with 0"1 or end with 0"tr1 An exam"!e o$ a "ointer dec!aration can be /
char *chptr;
+n the above dec!aration, 0char1 signi$ies the "ointer ty"e, ch"tr is the name o$ the "ointer whi!e the asterisk 061 signi$ies that 0ch"tr1 is a "ointer variab!e&
8ote that the ty"e o$ variab!e above shou!d be same as the "ointer ty"e&('hough this is not a strict ru!e but $or beginners this shou!d be ke"t in mind#& 9or exam"!e /
char ch = 'c'; char *chptr = ch; !!initiali"e OR char ch = 'c'; char *chptr; chptr = ch !!initiali"e
+n the code above, we dec!ared a character variab!e ch which stores the va!ue 0c1& 8ow, we dec!ared a character "ointer 0ch"tr1 and initia!i7ed it with the address o$ variab!e 0ch1&
8ote that the 0:1 o"erator is used to access the address o$ any ty"e o$ variab!e&
How to se a Pointer?
A "ointer can be used in two contexts& %ontext 1/ 9or accessing the address o$ the variab!e whose memory address the "ointer stores& Again consider the $o!!owing code /
char ch = 'c'; char *chptr = ch;
8ow, whenever we re$er the name 0ch"tr1 in the code a$ter the above two !ines, then com"i!er wou!d try to $etch the va!ue contained by this "ointer variab!e, which is the address o$ the variab!e (ch# to which the "ointer "oints& i&e& the va!ue given by 0ch"tr1 wou!d be e;ua! to 0:ch1& 9or exam"!e /
char *ptr = chptr;
'he va!ue he!d by 0ch"tr1 (which in this case is the address o$ the variab!e 0ch1# is assigned to the new "ointer 0"tr1& %ontext 2/ 9or accessing the va!ue o$ the variab!e whose memory address the "ointer stores& %ontinuing with the "iece o$ code used above /
char ch = 'c'; char t; char *chptr = ch; t = *chptr;
<e see that in the !ast !ine above, we have used 061 be$ore the name o$ the "ointer& <hat does this asterisk o"erator do= <e!!, this o"erator when a""!ied to a "ointer variab!e name(!ike in the !ast !ine above# yie!ds the va!ue o$ the variab!e to which this "ointer "oints& <hich means, in this case 06ch"tr1 wou!d yie!d the va!ue ke"t at address he!d by ch"tr& ,ince 0ch"tr1 ho!ds the address o$ variab!e 0ch1 and va!ue o$ 0ch1 is 0c1, so 06ch"tr1 yei!ds 0c1& <hen used with "ointers, the asterisk 061 o"erator is a!so known as 0va!ue o$1 o"erator&
#incl$de <stdio%h> int main(void) & char ch = 'c'; char *chptr = ch; int i = '(; int *intptr = i;
float f = )%'((((; float *fptr = f; char *ptr = *+ am a strin,*; printf(*-n ./c01 ./d01 ./f01 ./c01 ./s0-n*1 *chptr1 *intptr1 *fptr1 *ptr1 ptr); 2 ret$rn (;
>A'5A' /
3 %!pointers .c01 .'(01 .)%'(((((01 .+01 .+ am a strin,0
'o debug a % "rogram, use gdb& 'he above code covers a!! the common "ointers& 'he $irst three o$ them are very trivia! now to understand so !ets concentrate on the $ourth one& +n the $ourth exam"!e, a character "ointer "oints to a string& +n %, a string is nothing but an array o$ characters& ,o we have no staring "ointers in %& +ts the character "ointers that are used in case o$ strings too& 8ow, coming to the string, when we "oint a "ointer to a string, by de$au!t it ho!ds the address o$ the $irst character o$ the string& Lets try to understand it better& 'he string, 0+ am ,tring1 in memory is "!aced as /
)(() + )((' a )((4 m )((5 ; )((6 t )((7 r )((8 i )((9 n )((: , )()( -(
,ince characters occu"y one byte each, so they are "!aced !ike above in the memory& 8ote the !ast character, its a nu!! character which is "!aced at the end o$ every string by de$au!t in %& 'his nu!! character signi$ies the end o$ the string& 8ow coming back to the "oint, any character "ointer "ointing to a string stores the address o$ the $irst character o$ the string& +n the code above, 0"tr1 ho!ds the address o$ the character 0+1 ie 1001& 8ow, when we a""!y the 0va!ue o$1 o"erator 061 to 0"tr1, we intend to $etch the va!ue at address 1001 which is 0+1 and hence when we "rint 06"tr1, we get 0+1 as the out"ut& A!so, +$ we s"eci$y the $ormat s"eci$ier as 0Bs1 and use 0"tr1 (which contains the starting address o$ the string#, then the com"!ete string is "rinted using "rint$& 'he conce"t is that Bs s"eci$ier re;uires the address o$ the beginning byte o$ string to dis"!ay the com"!ete string,
which we "rovided using 0"tr1 (which we know ho!ds the beginning byte address o$ the string#& 'his we can see as the !ast "rint in the out"ut above&
ob<;
>A'5A'/
3 %!pointers .60 .a0
+n the above code, we have dec!ared a "ointer stob o$ ty"e 0struct st1& 8ow since the "ointer ty"e is a structure, so the address it "oints to has to be o$ a 0struct st1 ty"e variab!e(which in this case is 0ob 1#& >ther interesting "art is how structure e!ements are accessed using "ointer variab!e 0stob 1& Ces, <hen dea!ing with "ointer ob ects, its a standard to use arrow o"erator 4D instead o$ 0&1 o"erator(which wou!d have been used, had we used 0ob 1 to access the structure e!ements#& 'o conc!ude, +n this artic!e we studied the conce"t o$ "ointers in % $rom scratch and then s!ow!y bui!t u"on our understanding to more com"!ex to"ics !ike using "ointers as structure ob ects& 'his was a basic tutoria!, we wi!! cover more com"!ex "ointer conce"ts in the "art4++ o$ this artic!e& (5art 2/ Advanced % "ointers#&
C Pointer to Pointer& Pointer to Functions& !rra' o" Pointers Explained with Examples
by Himanshu Arora on Eanuary 23, 2012 +n % "rogramming !anguage, the conce"t o$ "ointers is the most "ower$u! conce"t that makes % stand a"art $rom other "rogramming !anguages& +n the "art4+ o$ this series we discussed the $undamenta! conce"ts around % "ointers& +n this artic!e, we wi!! try to deve!o" understanding o$ some o$ the re!ative!y com"!ex conce"ts& 'he $o!!owing are ex"!ained in this artic!e with exam"!es/ 1& 2& @& 2& %onstant "ointer and "ointer to constant& 5ointer to "ointer with an exam"!e Array o$ "ointers with an exam"!e 5ointer to $unctions with an exam"!e
C Constant pointer
A "ointer is said to be constant "ointer when the address its "ointing to cannot be changed& Lets take an exam"!e /
char ch1 c; char *ptr = ptr = c ch
+n the above exam"!e we de$ined two characters (0ch1 and 0c1# and a character "ointer 0"tr1& 9irst, the "ointer 0"tr1 contained the address o$ 0ch1 and in the next !ine it contained the address o$ 0c1& +n other words, we can say that +nitia!!y 0"tr1 "ointed to 0ch1 and then it "ointed to 0c1& *ut in case o$ a constant "ointer, once a "ointer ho!ds an address, it cannot change it& 'his means a constant "ointer, i$ a!ready "ointing to an address, cannot "oint to a new address& +$ we see the exam"!e above, then i$ 0"tr1 wou!d have been a constant "ointer, then the third !ine wou!d have not been va!id& A constant "ointer is dec!ared as /
9or exam"!e /
#incl$de<stdio%h> int main(void) & char ch = 'c'; char c = 'a'; char *const ptr = ch; !! = constant pointer ptr = c; !! >ryin, to assi,n ne? address to a constant pointer% @ROABCCCC 2 ret$rn (;
<hen the code above is com"i!ed, com"i!er gives the $o!!owing error /
3 ,cc -@all constptr%c -o constptr constptr%cD +n f$nction EmainFD constptr%cD:D errorD assi,nment of read-only variable EptrF
,o we see that, as ex"ected, com"i!er throws an error since we tried to change the address he!d by constant "ointer& 8ow, we shou!d be c!ear with this conce"t& Lets move on&
C Pointer to Constant
'his conce"t is easy to understand as the name sim"!i$ies the conce"t& Ces, as the name itse!$ suggests, this ty"e o$ "ointer cannot change the va!ue at the address "ointed by it& Lets understand this through an exam"!e /
char ch = 'c'; char *ptr = ch *ptr = 'a';
+n the above exam"!e, we used a character "ointer 0"tr1 that "oints to character 0ch1& +n the !ast !ine, we change the va!ue at address "ointer by 0"tr1& *ut i$ this wou!d have been a "ointer to a constant, then the !ast !ine wou!d have been inva!id because a "ointer to a constant cannot change the va!ue at the address its "ointing to& A "ointer to a constant is dec!ared as /
const <type-of-pointer> *<name-of-pointer>;
9or exam"!e /
#incl$de<stdio%h> int main(void)
&
char ch = 'c'; const char *ptr = ch; !! = constant pointer 'ptr' pointin, to 'ch' *ptr = 'a';!! @ROABCCC Gannot chan,e the val$e at address pointed by 'ptr'% 2 ret$rn (;
<hen the above code was com"i!ed, com"i!er gave the $o!!owing error /
3 ,cc -@all ptr'const%c -o ptr'const ptr'const%cD +n f$nction EmainFD ptr'const%cD8D errorD assi,nment of read-only location E*ptrF
,o now we know the reason behind the error above ie we cannot change the va!ue "ointed to by a constant "ointer&
*) C Pointer to Pointer
'i!! now we have used or !earned "ointer to a data ty"e !ike character, integer etc& *ut in this section we wi!! !earn about "ointers "ointing to "ointers& As the de$inition o$ "ointer says that its a s"ecia! variab!e that can store the address o$ an other variab!e& 'hen the other variab!e can very we!! be a "ointer& 'his means that its "er$ect!y !ega! $or a "ointer to be "ointing to another "ointer& Lets su""ose we have a "ointer 0"1G that "oints to yet another "ointer 0"2G that "oints to a character 0ch1& +n memory, the three variab!es can be visua!i7ed as /
,o we can see that in memory, "ointer "1 ho!ds the address o$ "ointer "2& 5ointer "2 ho!ds the address o$ character 0ch1& ,o 0"2G is "ointer to character 0ch1, whi!e 0"1G is "ointer to 0"2G or we can a!so say that 0"2G is a "ointer to "ointer to character 0ch1& 8ow, in code 0"2G can be dec!ared as /
char *p' = ch;
,o we see that 0"1G is a doub!e "ointer (ie "ointer to a "ointer to a character# and hence the two 6s in dec!aration& 8ow,
0"1G is the address o$ 0"2G ie 5000 06"1G is the va!ue he!d by 0"2G ie H000 066"1G is the va!ue at H000 ie 0c1
+ think that shou!d "retty much c!ear the conce"t, !ets take a sma!! exam"!e /
#incl$de<stdio%h> int main(void) & char **ptr = AHII; char *p = AHII; char c = 'd'; p = c; ptr = p; printf(*-n c = ./c0-n*1c); printf(*-n *p = ./c0-n*1*p); printf(*-n **ptr = ./c0-n*1**ptr); ret$rn (; 2
9or exam"!e /
char *ptr.40;
'he above !ine dec!ares an array o$ three character "ointers& Lets take a working exam"!e /
#incl$de<stdio%h> int main(void) & char *p) = *Jimansh$*; char *p' = *=rora*; char *p4 = *+ndia*; char *arr.40; arr.(0 = p); arr.)0 = p'; arr.'0 = p4; printf(*-n p) = ./s0 -n*1p)); printf(*-n p' = ./s0 -n*1p'); printf(*-n p4 = ./s0 -n*1p4); printf(*-n arr.(0 = ./s0 -n*1arr.(0); printf(*-n arr.)0 = ./s0 -n*1arr.)0); printf(*-n arr.'0 = ./s0 -n*1arr.'0); ret$rn (; 2
+n the above code, we took three "ointers "ointing to three strings& 'hen we dec!ared an array that can contain three "ointers& <e assigned the "ointers 0"1G, 0"2G and 0"@G to the 0,1 and 2 index o$ array& Let1s see the out"ut /
3 %!arrayofptr p) = .Jimansh$0 p' = .=rora0 p4 = .+ndia0 arr.(0 = .Jimansh$0 arr.)0 = .=rora0 arr.'0 = .+ndia0
,) C Function Pointers
Eust !ike "ointer to characters, integers etc, we can have "ointers to $unctions& A $unction "ointer can be dec!ared as /
10
9or exam"!e /
int (*fptr)(int1 int)
'he above !ine dec!ares a $unction "ointer 0$"tr1 that can "oint to a $unction whose return ty"e is 0int1 and takes two integers as arguments& Lets take a working exam"!e /
#incl$de<stdio%h> int f$nc (int a1 int b) & printf(*-n a = /d-n*1a); printf(*-n b = /d-n*1b); ret$rn (; 2 int main(void) & int(*fptr)(int1int); !! K$nction pointer fptr = f$nc; !! =ssi,n address to f$nction pointer f$nc('14); fptr('14); ret$rn (; 2
+n the above exam"!e, we de$ined a $unction 0$unc1 that takes two integers as in"uts and returns an integer& +n the main(# $unction, we dec!are a $unction "ointer 0$"tr1 and then assign va!ue to it& 8ote that, name o$ the $unction can be treated as starting address o$ the $unction so we can assign the address o$ $unction to $unction "ointer using $unction1s name& Lets see the out"ut /
3 %!fptr a = ' b = 4 a = ' b = 4
,o $rom the out"ut we see that ca!!ing the $unction through $unction "ointer "roduces the same out"ut as ca!!ing the $unction $rom its name& 'o conc!ude, in this artic!e we touched some o$ the advanced conce"ts re!ated to "ointers& 'here can be some interesting "rob!ems re!ated to "ointers, which we might cover in some $uture artic!e&
11
Constant Pointers
Lets $irst understand what a constant "ointer is& A constant "ointer is a "ointer that cannot change the address its ho!ding& +n other words, we can say that once a constant "ointer "oints to a variab!e then it cannot "oint to any other variab!e& A constant "ointer is dec!ared as $o!!ows /
<type of pointer> * const <name of pointer>
<e dec!ared two variab!es var1 and var2 A constant "ointer 0"tr1 was dec!ared and made to "oint var1 8ext, "tr is made to "oint var2& 9ina!!y, we try to "rint the va!ue "tr is "ointing to&
,o, in a nutshe!!, we assigned an address to a constant "ointer and then tried to change the address by assigning the address o$ some other variab!e to the same constant "ointer&
12
,o we see that whi!e com"i!ing the com"i!er com"!ains about 0"tr1 being a read on!y variab!e& 'his means that we cannot change the va!ue "tr ho!ds& Hence we conc!ude that a constant "ointer which "oints to a variab!e cannot be made to "oint to any other variab!e&
Pointer to Constant
As evident $rom the name, a "ointer through which one cannot change the va!ue o$ variab!e it "oints is known as a "ointer to constant& 'hese ty"e o$ "ointers can change the address they "oint to but cannot change the va!ue ke"t at those address& A "ointer to constant is de$ined as /
const <type of pointer>* <name of pointer>
<e de$ined a variab!e var1 with va!ue 0 we de$ined a "ointer to a constant which "oints to variab!e var1 8ow, through this "ointer we tried to change the va!ue o$ var1 Ased "rint$ to "rint the new va!ue&
,o we see that the com"i!er com"!ains about 06"tr1 being read4on!y& 'his means that we cannot change the va!ue using "ointer 0"tr1 since it is de$ined a "ointer to a constant& 1@
$or exam"!e /
const int* const ptr;
var);
<e dec!ared two variab!es var1 and var2& <e dec!ared a constant "ointer to a constant and made it to "oint to var1 8ow in the next two !ines we tried to change the address and va!ue "ointed by the "ointer&
,o we see that the com"i!er com"!ained about both the va!ue and address being changed& Hence we conc!ude that a constant "ointer to a constant cannot change the address and va!ue "ointed by it&
12