home *** CD-ROM | disk | FTP | other *** search
- .NT
- A NOTE ABOUT THE LESSONS in C
- .b4-24
- .R5C4
- These were written while the author was ~Ilearning~N the language and since
- .R6C4
- they are ~Ifree~N ( to copy and/or distribute ) there is a money-back
- .R7C4
- guarantee on the accuracy of each and every statement in the lessons (!)
- .R9C4
- The ~Idisplay~N program was written ( in C ) in order to provide a vehicle
- .R10C4
- for displaying the lessons.
- .R12C5
- .B
- P.J.Ponzo
- .B
- Dept. of Applied Math
- .B
- Univ. of Waterloo
- .B
- Ontario N2L 3G1
- .K16,30
- PonzoTUTOR
- .WNT
- POINTERS and ARRAYS
- .R4C1
- Recall that, when we refer to ~b~I&x~N, ~IC~N will interpret this as the
- ~Iaddress~N in memory of the variable ~b~Ix~N. Here ~b~I&x~N is a ~w~Rpointer~N.
-
- If we set ~b~Iy=&x~N, in our program, then ~b~Iy~N ~w~Rpoints~N to the
- variable ~b~Ix~N ( ~b~Iy~N is now an address, in memory ).
-
- .b9-11
- .R10C17
- ~V HOW DO WE DECLARE A POINTER VARIABLE ? ~N
- .W
- .R10C17
- ~V patience ~N
-
- In addition to the ~b~I&~N ~Ioperator~N (which returns the ~Iaddress~N of
- the variable which follows it), there is the C ~Ioperator~N ~b~I*~N.
-
- If ~b~Iy~N points to ~b~Iint x~N, then ~b~I*y~N is the ~Icontents of memory~N
- ~Ilocation y~N. When a program refers to ~b~I*y~N, the C compiler will go
- to the address given by the ~w~Rpointer~N ~b~Iy~N, extract the ~b~Iint~Neger
- it finds there, and use this ~b~Iint~Neger in place of ~b~I*y~N.
-
- This poses a problem.....
- .K19,60
- a problem?
- .WN
-
- How is the compiler to know whether the contents of the address ~b~Iy~N,
- (which we refer to as ~b~I*y~N, in our program) is an ~b~Iint~Neger or a
- ~b~Ifloat~Ning point number or a ~b~Ichar~Nacter variable ???
-
- Since an ~b~Iint~Neger occupies ~I2~N bytes ( usually ..depending upon the
- computer you are using) and a single ~b~Ichar~Nacter variable occupies
- just ~I1~N byte and a ~b~Ifloat~N occupies ~I4~N bytes ...etc. etc...then
- it's clearly important that the compiler KNOW that ~b~Iy~N is pointing to
- an ~b~Iint~N or a ~b~Ichar~N or a ~b~Ifloat~N ...etc.
-
- ~ISO ... we must declare the type of variable that ~b~Iy~N points to !~N
-
- To do this we declare ~Ithe contents of y~N, namely ~b~I*y~N !!
- .K19,60
- example?
- .WN
- 1 ~b~Imain() { ~N
- 2 ~b~I int *y; ~N
- 3 ~b~I int x=123; /* x=integer 123 */~N
- 4 ~b~I y=&x; /* y=address of x */~N
- 5 ~b~I printf("The value of x is %d",*y); ~N
- 6 ~b~I} ~N
- This program will (correctly) print: ~r~IThe value of x is 123~N
- .K19,60
- int *y;
-
- Note that, in line 4, ~b~Iy~N is made a ~w~Rpointer~N, pointing to ~b~Ix~N
- and ~b~Ix~N is an ~b~Iint~N .... ~ISO~N ... in line 2 we declare our
- ~w~Rpointer~N ~b~Iy~N as: ~b~I int *y ~N since it points to an ~b~Iint~N.
- .K19,60
- all clear?
- .WN
-
- ~V ~N
- ~V REMEMBER!! IF sam IS A POINTER TO SOME VARIABLE, ~N
- ~V THEN BE SURE TO DECLARE *sam AS THE SAME ~N
- ~V TYPE AS THE VARIABLE TO WHICH sam POINTS! ~N
- ~V ~N
- .b1-7
- .K19,32
- mamma mia!
- .R10C1
- If ~b~Ix~N is an ~Iint~N and ~b~Iy=&x~N then declare : ~b~Iint *y~N
- If ~b~Ix~N is a ~Ichar~N and ~b~Iy=&x~N then declare : ~b~Ichar *y~N
- If ~b~Ix~N is a ~Ifloat~N and ~b~Iy=&x~N then declare : ~b~Ifloat *y~N
- .WNT
- VARIABLES and their HOMES in MEMORY
- We've mentioned that the ~b~Ichar c~N occupies ~I1~N byte of memory, and
- that ~b~Iint i~N occupies ~I2~N bytes and ~b~Ifloat f~N occupies ~I4~N bytes.
-
- Suppose ~b~Ipc=&c~N is a ~w~Rpointer~N to ~b~Ic~N, and ~b~Ipi=&i~N and ~b~Ipf=&f~N.
-
- ~V WHERE DOES pc+1 POINT TO ? ~N
-
- and ~V WHERE DOES pi+1 POINT TO ? ~N
-
- and ~V WHERE DOES pf+1 POINT TO ? ~N
- .K16,32
- I give up!
- .WN
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .R4C2
- pc-2 pc-1 pc pc+1 pc+2 pc+3 pc+4 pc+5 pc+6 pc+7 pc+8
-
-
- If the boxes are each ~I1~N byte of memory, and ~b~Ipc~N points to one
- such byte, then the scheme shown above indicates where ~b~Ipc-2~N, etc.
- point to.
-
- The fact that ~b~Ipc~N is a ~w~Rpointer~N to a ~b~Ichar~N (because we would
- (should?) have declared it with ~b~Ichar *pc~N) and because a ~b~Ichar~N
- only occupies ~I1~N byte, then ~IC~N is smart enough to know that ~b~Ipc-2~N
- is the address of the memory location 2 bytes below ~b~Ipc~N.
- .K16,32
- try int!
- .WN
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .R4C2
- pi-1 pi pi+1 pi+2 pi+3 pi+4
-
- Now ~b~Ipi~N points to a (~I2~N byte) ~b~Iint~N, so ~IC~N (whatta guy!)
- arranges that ~b~Ipi-1~N points ~I2~N bytes earlier than ~b~Ipi~N ...that
- way it will point to the IMMEDIATELY PRECEDING ~b~Iint~N.
-
- (...of course, who knows if there IS an ~b~Iint~N stored at ~b~Ipc-1~N ?!)
- .W
- .K16,32
- .WN
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .B
-
- .R4C2
- pf pf+1 pf+2
-
- You guessed it! ~b~Ipf+1~N will point to the VERY NEXT ~b~Ifloat~N,
- ~I4~N bytes past where ~b~Ipf~N points.
-
- (...ain't ~Iaddress arithmetic~N wonderful ? )
-
- NOTE:If we have ~b~Imain() { ~N
- ~b~I float f, *pf; ~N
- ~b~I f=12.3; ~N
- ~b~I pf=&f; ~N
-
- then what IS ~I4~N bytes past the address of ~b~If~N ???
-
- There is one circumstance where we WILL know "what comes after".
- .K19,60
- GUESS!
- .WNT
- hip hip ARRAYS
- .R4C1
- You may recall, from an earlier lesson, that we defined a string by
- declaring it to be an ARRAY of (single) ~b~Ichar~Nacters.
-
- We'll reproduce it here:
-
- ~b~Ichar x[10];~N defines an ~IARRAY~N of ~b~I10~N elements.
- ~b~Ix[0]='A';~N the first element is the character ~b~IA~N.
- ~b~Ix[1]='b';~N the second element is the character ~b~Ib~N.
- ~b~Ix[2]='{';~N the third element is the character ~b~I{~N.
- ~b~Ix[3]='\0';~N the last element is the 'number' ~I0~N!!!!
- ~b~Iprintf("the string is %s",x);~N print the string, up to the ~I0~N.
-
- ...and the printout would be: ~r~Ithe string is Ab{~N
- .K19,60
- remember?
- .WN
- ~b~Imain() { ~N
- ~b~I char x[10], *px; ~N
- ~b~I x[0]='A'; ~N
- ~b~I x[1]='b'; ~N
- ~b~I x[2]='{'; ~N
- ~b~I x[3]='\0'; ~N
- ~b~I printf("the string is %s",x); ~N
-
-
- NOW, if we define ~b~Ipx=&x[0]~N, a ~w~Rpointer~N to the first element in
- the ARRAY ~b~Ix[]~N, then:
- .W
- .Q
- What character does px+2 point to ?
- {
- ~b~Iprintf("%c%c%c",*px,*(px+1),*(px+2));~N
- .Q
- What will the above print?
- Ab{
-
- ~b~Iprintf("%c",*px);~N would print the contents of memory location
- ~b~Ipx~N, namely ~r~IA~N, and ~b~Iprintf("%c",*(px+1));~N prints ~r~Ib~N,
- and ~b~Iprintf("%c",*(px+2));~N prints ~r~I{~N, and ALL THREE GIVE: ~r~IAb{~N.
-
- ( ...a-a-a-h, C is ~Iso~N clever ...)
- .K2,60
- whatta gal
- .WN
- 1 ~b~I char x[4]; ~N
- 2 ~b~I x[0]='A'; ~N
- 3 ~b~I x[1]='b'; ~N
- 4 ~b~I x[2]='{'; ~N
- 5 ~b~I x[3]='\0'; ~N
- In this program excerpt, we defined some elements of the ARRAY ~b~Ix[10]~N
- by saying ( laboriously ):~b~Ix[0]='A'; x[1]='b'; x[2]='{'; x[3]='\0';~N
-
- For a ~b~Ichar~N ARRAY we can also say:
-
- ~b~Ichar x[4]={ 'A','b','{','\0' };~N
-
- making Lines 2-5 unnecessary.
-
- For an ~b~Iint~N ARRAY we can say:
-
- ~b~Iint x[3]={11,12,13};~N
-
- Under certain conditions, all ARRAYS may be ~Iinitialized~N (defined as they
- are declared). We'll talk about this later ...
- .K10,60
- curly {
- .WNT
- More POINTERS and ARRAYS
- .R4C1
- When we define an ARRAY, say: ~b~I int s[10];~N then each of ~b~Is[0]~N,
- ~b~Is[1]~N, etc are (~I2~N byte) ~b~Iint~Negers.
-
- ~I...and here's something special:~N
- .b6-8
- .R10C1
- ~b~Is~N, all by itself, is a ~w~Rpointer~N to ~b~Is[0]~N
- .b9-11
- .K19,60
- WHAT!
- .W
- .R12C1
- 1 ~b~Imain() { ~N
- 2 ~b~I int s[3]; /* define integer array */ ~N
- 3 ~b~I s[0]=11; s[1]=12; s[2]=13; /* define members of s[] */ ~N
- 4 ~b~I printf("%d",s[0]); /* print first integer */ ~N
- 5 ~b~I printf("\n%d",*s); /* print what s points to*/ ~N
- 6 ~b~I} ~N
- Line 4 will print ~r~I11~N and line 5 will print ~r~I11~N !!!
- ..proving that s[0] and *s are the same, right?
- ..so ~Is is a pointer to s[0]~N, right?
- .K19,60
- RIGHT!
- .W
- Of course it would have been easier to say:
- 2 ~b~Iint s[3]={11,12,13};~N and omit Line 3!
- .WN
- NOW, since an ARRAY (~Iany~N ARRAY, whether ~b~Iint~Ns or ~b~Ichar~Ns or ~b~Ifloats~N)
- ~Vhas its name as a pointer~N (..think about that! ), then not only will ~b~Is[2]~N
- give the 3rd element in the ARRAY, ~Ibut so will *(s+2) give the 3rd element!~N
-
- Here's a program you've seen in an earlier lesson (on STRINGS):
-
- 1 ~b~Imain() { ~N
- 2 ~b~I char s; /* declare a char */ ~N
- 3 ~b~I s="I am a string"; /* make it a string */ ~N
- 4 ~b~I printf("%s",s); /* print the string */ ~N
- 5 ~b~I printf("\n%s",s+2); /* what ????? */ ~N
- 6 ~b~I} ~N
-
- Line 2 declares ~b~Is~N to be of type ~b~Ichar~N.
- Line 3 defines ~b~Is~N to be a string ( double quotes, remember?).
- Line 4 prints the ~b~I%s~Ntring, giving ~r~II am a string~N
- Line 5 prints .... ~r~Iam a string~N
- .W
-
- Here, just as for an ARRAY, ~b~Is~N is a ~w~Rpointer~N to the string
- ~b~I"I am a string"~N. In fact, ~b~Is~N points to the first element: ~b~II~N.
- HENCE, ~b~Is+2~N points to the ~I3rd element~N (~b~Ia~N) and ~b~Iprintf()~N will
- (upon receipt of a ~b~I%s~Ntring address) print everything from that
- address up to the special terminating ~I'\0'~N ( ...remember him?).
- .WK7,32
- magnifico!
- .WN
-
-
-
-
-
-
- ~ITHE NAME OF A STRING VARIABLE IS A POINTER TO THE FIRST ELEMENT IN THE STRING!
-
- ~ITHE NAME OF AN ARRAY VARIABLE IS A POINTER TO THE FIRST ELEMENT IN THE ARRAY !
- .b5-11
- ~I
- .K16,32
- REMEMBER!
- .WR3C1
- ...and ~r~Ipointer~N arithmetic is wonderful...
- .b2-4
- .WNT
- Be kind to your compiler
- .R4C1
- Now, if we declare ~b~Ichar a[30];~N the C-compiler knows that ~b~Ia~N refers
- to a collection of ~I30~N ~b~Ichar~Ns ...and it knows this even before we define
- the elements ~b~Ia[0]~N, ~b~Ia[1]~N, etc.
-
- BUT, if we declare ~b~Ichar s;~N, how is the compiler to know whether ~b~Is~N
- if a single ~b~Ichar~N or a string of ~b~Ichar~Ns. If, subsequently, we say
- ~b~Is="I am a string"~N then ~b~Is~N IS a string ..but if we say ~b~Is='A'~N
- then ~b~Is~N is just one ~b~Ichar~N ...but should we REALLY make the compiler
- figure this out? After all, the compiler would reserve a single byte in
- memory for just one ~b~Ichar~N but may have to reserve dozens of bytes for
- a string of ~b~Ichars~N!
-
- ~VMORAL~N: DECLARE A SINGLE CHARACTER AS ~b~Ichar s;~N
- DECLARE A STRING OF CHARS AS ~b~Ichar *s;~N
- .b15-18
-
- Since we (and the compiler) know that the name of a string is a ~w~Rpointer~N
- then the declaration ~b~Ichar *s;~N (followed perhaps by ~b~Is="I'm a string"~N)
- just anticipates the subsequent use of ~b~Is~N as the name of a string (as
- opposed to a single character).
- .WNR3
- ~b~I ~N
- ~b~I char s; ~N
- ~b~I s="I am a string"; ~N
- ~b~I printf("%s",s); ~N
- ~b~I ~N
-
- Although we have used the above format in earlier lessons .....
-
- .B
- IT MAY NOT COMPILE!
- .R14C1
- ...and if it does
-
- .B
- IT MAY NOT WORK!
- .WR4C40
- ~b~I char *s; ~N
- .R21B
- If we use ~b~Ichar *s~N then ALL compilers will accept it.
- .WN
- We have:
-
- If ~b~Is~N is the name of a string (defined with ~Idouble quotes~N) then
- ~b~Is~N ~b~Is+1~N ~b~Is+2~N etc ~w~Rpoint~N to the ~I1st~N ~I2nd~N ~I3rd~N etc.
- members of the string.
- .b2-6
- .R8C1
- If ~b~Is~N is the name of an ARRAY (defined with ~b~Is[0]=...~N etc.) then
- ~b~Is~N ~b~Is+1~N ~b~Is+2~N etc ~w~Rpoint~N to the ~I1st~N ~I2nd~N ~I3rd~N etc.
- members of the ARRAY.
- .b7-11
- .K17,60
- hmmmmmm...
- .WN
- Now, don't think that strings and ARRAYs are the same ...after all a string
- is only an ~IARRAY of (single) ~bchar~N~I variables~N whereas we can also have
- ARRAYs of ~b~Iint~Ns or ~b~Ifloats~N or other interesting ~Idata types~N.
- .W
-
- Further, the name of a string pointer is a VARIABLE:
-
- 1 ~b~Imain() { ~N
- 2 ~b~I char *x, *y, *z; /* 3 pointers to strings */ ~N
- 3 ~b~I x="ABC"; /* x points to string ABC */ ~N
- 4 ~b~I y="DEF"; /* y points to string DEF */ ~N
- 5 ~b~I z=x; /* z points to string ABC */ ~N
- 6 ~b~I printf(" The x-string is %s",z); ~N
- 7 ~b~I z=y; /* z points to string DEF */ ~N
- 8 ~b~I printf(" The y-string is %s",z); ~N
- 9 ~b~I ~N
- In line 5 we make ~b~Iz~N point to the same thing that ~b~Ix~N points to
- ...and line 6 prints: ~r~I The x-string is ABC~N
-
- In line 7 we make ~b~Iz~N point to the same thing that ~b~Iy~N points to
- ...and line 8 prints: ~r~I The y-string is DEF~N
- .W
- BUT, we could also say: ~b~Ix=y;~N and make ~b~Ix~N point to the y-string!
- .WNT
- STRINGS and 1-dimensional CHAR ARRAYS
- .R4C1
- Suppose we may declare strings ~b~Ic~N and ~b~Ix~N by using:
-
- 1 ~b~Ichar c[9]={'c','-','s','t','r','i','n','g','\0'}; ~N
- 2 ~b~Ichar *x="x-string"; ~N
-
- In the first instance, ~b~Ic~N is a ~r~Ipointer~N to an ARRAY of ~b~Ichar~Nacter
- variables (8 ~b~Ichar~Ns: ~Ic-string~N , plus the terminating '\0').
-
- In the second instance, ~b~Ix~N is ~Ialso~N a ~r~Ipointer~N, but now it's a
- ~r~Ipointer~N to a ~Istring~N: ~b~Ix-string~N with (again) the terminating
- '\0' (which ~IC~N looks after appending).
-
- SO WHAT'S THE DIFFERENCE BETWEEN char c[] and char *x ???
- .K19,60
- I give up
- .WN
- 1 ~b~Ichar c[9]={'c','-','s','t','r','i','n','g','\0'}; ~N
- 2 ~b~Ichar *x="x-string"; ~N
-
- In the first case, ~b~Ic~N is a ~ICONSTANT POINTER~N to the first element of
- the ARRAY ...and ~Icannot be changed~N.
- In the second case, ~b~Ix~N is a ~IVARIABLE POINTER~N to the first element of
- the string ...and ~ICAN~N be changed!
- .K19,32
- WHAT!
- .WN
- 1 ~b~Ichar c[9]={'c','-','s','t','r','i','n','g','\0'}; ~N
- 2 ~b~Ichar *x="x-string"; ~N
- 3 ~b~Iprintf(" %s %s ",c,x); /* print %strings c and x */ ~N
- 4 ~b~Ix=c; /* make x point to c */ ~N
- 5 ~b~Iprintf(" %s %s ",c,x); /* print %strings c and x */ ~N
-
- Just to show that it is ~b~Ix~N (and ~INOT~N ~b~Ic~N) which is a VARIABLE,
- we declare/define them both in Lines 1 and 2.
- Then print them both in Line 3. We would get:
-
- ~r~I c-string x-string~N
-
- Then we ~Ichange x~N, in Line 4, so it points to the same thing as ~b~Ic~N does,
- then print them both again, in Line 5. We'd get:
-
- ~r~I c-string c-string~N
-
- You must not try: ~b~Ic=x;~N because it won't compile!
-
- ARRAY names point (ALWAYS and FOREVER) to the first element of the ARRAY!
- .b19-21
- .WNT
- more and more ARRAYS
- .R4C1
- In addition to an ARRAY such as ~b~Ix[10]~N (with 10 elements,
- which may be char,int,float,etc.),here's a ~Idouble ARRAY~N:
-
- ~b~Ifloat x[5][7];~N This declares an ARRAY of 5*7=~I35~N
- floating point numbers. We may define any or all
- of them (for example we may write ~b~Ix[2][1]=1.5~N).
- We think of this ARRAY as being arranged like so:
- .R12C1
- x[0][0] x[0][1] x[0][2] x[0][3] x[0][4] x[0][5] x[0][6]
- x[1][0] x[1][1] x[1][2] x[1][3] x[1][4] x[1][5] x[1][6]
- x[2][0] x[2][1] x[2][2] x[2][3] x[2][4] x[2][5] x[2][6]
- x[3][0] x[3][1] x[3][2] x[3][3] x[3][4] x[3][5] x[3][6]
- x[4][0] x[4][1] x[4][2] x[4][3] x[4][4] x[4][5] x[4][6]
- .b11-17
- .K4,66
- x[i][j][k]
- .WR4C1
-
-
-
-
-
-
-
- .R4C1
- Now, if we define ~b~Ix[2][1]=1.5~N, the number 1.5 goes here!
- .sR14C20
- ~Fx[2][1]~N
- .r
-
- ...and, as you might expect, we can have ~I3-dimensional~N ARRAYS, etc.
- .rK4,66
- x[i][j][k]
- .WN
- ~V x[0][0] x[0][1] x[0][2] x[0][3] x[0][4] x[0][5] x[0][6] ~N
- ~V x[1][0] x[1][1] x[1][2] x[1][3] x[1][4] x[1][5] x[1][6] ~N
- ~V x[2][0] x[2][1] x[2][2] x[2][3] x[2][4] x[2][5] x[2][6] ~N
- ~V x[3][0] x[3][1] x[3][2] x[3][3] x[3][4] x[3][5] x[3][6] ~N
- ~V x[4][0] x[4][1] x[4][2] x[4][3] x[4][4] x[4][5] x[4][6] ~N
- When we declare a multi-dimensional ARRAY, as in ~b~Ifloat x[5][~F7~N~b~I]~N, the
- C-compiler knows that each element occupies ~I4 bytes~N in memory (because
- it's an ARRAY of ~b~Ifloat~Ns) ..hence it knows not only how much memory
- is needed but where each element is. Starting at the ~Iaddress~N of the first
- element, ~b~I&x[0][0]~N, we find the ~Iaddress~N of ~b~Ix[~F2~N~b~I][~F1~N~b~I]~N by moving
- ~F~I7~N*~F~I2~N+~F~I1~N=15 elements along the ARRAY ...and at 4-bytes-per-element
- that means moving 4*15=60 bytes through memory.
-
- Notice how important the number of ~Icolumns~N is to the C-compiler (in the
- declaration ~b~Ifloat x[5][7]~N
- Without this dimension the compiler wouldn't know how to get to ~b~Ix[2][1]~N!
-
- In fact, ~IYOU MAY LEAVE OUT THE NUMBER OF ROWS IN DECLARING THIS ARRAY!~N
-
- (and use ~b~Ifloat x[][7]~N instead!)
- .WR6C1s
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- .r
- A 2-dimensional ARRAY is treated (by ~IC~N) as a 1-dimensional ARRAY each
- of whose elements is a 1-dimensional ARRAY.
-
- The ARRAY ~b~Ifloat x[5][7]~N consists of ~I5~N 1-dimensional ARRAYS, called
- (in C-speak), ~b~Ix[0]~N, ~b~Ix[1]~N, ~b~Ix[2]~N, etc. and each of these
- 1-dimensional ARRAYS has ~I7~N elements.
-
- Since (for example) the element 3 of an ARRAY ~b~Isam~N is called ~b~Isam[3]~N
- then element 3 of the (1-dimensional) ARRAY ~b~Ix[2]~N is called ~b~Ix[2][3]~N
- ... which explains the C-notation for 2-dimensional ARRAYS,
- x[i][j], rather than (the more usual) x[i,j].
-
- In fact, you may refer to ~b~Ix[2][3]~N as ~b~I(x[2])[3]~N ... meaning
- element 3 of the (1-dimensional) ARRAY x[2] (actually the 4th element
- since the first is element 0 !!!@#$*).
- .WR3C1
- ~V x[2][0] x[2][1] x[2][2] ~Fx[2][3]~N~V x[2][4] x[2][5] x[2][6] ~N
- .WN
-
-
- If ~IC~N regards ~b~Ix[5][7]~N as consisting of ~I5~N 1-dimensional ARRAYS
- ~b~Ix[0]~N, ~b~Ix[1]~N, ~b~Ix[2]~N, ~b~Ix[3]~N, and ~b~Ix[4]~N then what
- does (for example) ~b~Ix[2]~N refer to ? What happens if we printf() ~b~Ix[2]~N?
- Is ~b~Ix[2]~N just a notation or does it refer to one of the ~I5*7=35~N members
- of ~b~Ix[5][7]~N ?
- .b2-8
- .K10,32
- I give up!
- .WN
-
- Actually, ~IC~N is very clever. ~b~Ix[2]~N (all by itself) is a ~r~Ipointer~N to the
- first element in the 1-dimensional ARRAY ~b~Ix[2]~N, namely ~b~Ix[2][0]~N !
-
- ~IREMEMBER~N: Although ~b~Ix[2][0]~N gives the ~Ivalue~N of element ~b~Ix[2][0]~N,
- ~b~Ix[2]~N gives the ~Iaddress~N of ~b~Ix[2][0]~N!!
-
- Since ~b~Ix[2]~N is a ~r~Ipointer~N to ~b~Ix[2][0]~N, then ~Iaddress arithmetic~N
- can be used to obtain the ~Iaddress~N of any element in the 1-dimensional
- ARRAY ~b~Ix[2]~N.
-
- That means that we could identify the element ~b~Ix[i][j]~N
- by pointing just ~Ij~N elements past the address of ~b~Ix[i][0]~N.
-
- That means that ~b~Ix[i]+j~N is a ~r~Ipointer~N to ~b~Ix[i][j]~N
-
- That means that the 'value' of this element is ~b~I*(x[i]+j)~N.
-
- ~IREMEMBER~N: If x[i]+j is a pointer, then *(x[i]+j) is what it points to!
- .b4-7
- .b18-20
- .WK8,32
- MAMMA MIA!
- .R23C1
- ~Iand that means that *(x[2]+3) and x[2][3] are EQUIVALENT~N
- .b22-24
- .WNT
- What's in a name ? (of an ARRAY)
- .R6C1
- ~V ~N
- ~V The name of a 1-dimensional ARRAY is a ~N
- ~V POINTER to the first element of the ARRAY! ~N
- ~V ~N
- .b5-10
-
- SO, if ~b~Ix~N is an ARRAY, declared as ~b~Iint x[10]~N, then ~b~Ix~N
- is a ~r~Ipointer~N to ~b~Ix[0]~N (since ~b~Ix~N is 1-dimensional).
-
- AND, if ~b~Ix~N is an ARRAY, declared as ~b~Iint x[10][15]~N, then ~b~Ix[7]~N
- is a ~r~Ipointer~N to ~b~Ix[7][0]~N (since ~b~Ix[7]~N is 1-dimensional).
- .K19,32
- sounds OK!
- .WN
- .R10C1
- ...and finally, we may ~b~Iprintf("%d",x[7][2]); ~N to print the value of
-
- the element, OR we may ~b~Iprintf("%d",*(x[7]+2));~N.
- .b8-14
- .K19,32
- beautiful!
- .WN
-
-
- .T
- That's all folks!
- .K16,32
- au revoir!
-
-
- .q
-
-