# Category : C Source Code

Archive : TEACH-C.ZIP

Filename : LESSON6

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

[1mPonzoTUTOR

.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

[0;1;5mTRY FLOAT![0m

.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

[0;1mx[i][j][k][0m

.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

Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/