>co***********@hotmail.com wrote:
[edited for space]
void f(char **t) { printf("%s\n", *t); }
int main(void) {
char foo[256];
strcpy(foo, "bar");
f(&foo); /* WRONG */
In article <11**********************@g49g2000cwa.googlegroups .com>
John Bode <jo*******@my-deja.com> wrote:Ah, enlightenment dawns. Try something like this:
char *p = foo;
f(&p);
Indeed. A picture might also help:
foo:
+-----+-----+-----+-----+-----...-----+
| 'b' | 'a' | 'r' | 0 | (junk)... |
+-----+-----+-----+-----+-----...-----+
Here "foo" is an array of size 256 containing "char"s. Note that
there *is no pointer*, there is just the array named "foo", which
occupies 256 bytes.
Inside f(), assuming that **t == 'k' and that the printf()
will print (say) "k2":
t:
+----------------------+ +----------------------+
| *------------------> | * |
+----------------------+ +-----------|----------+
/
/
/
|
v
+-----+-----+-----+
| 'k' | '2' | 0 |
+-----+-----+-----+
Here there are *two* pointers: t, and *t. In this illustration
I drew them both as four bytes long (by making the boxes about
four times the size of the one-byte "char" boxes), but they could
be 2 or 3 or 4 or 8 or 128 bytes, or (on some rather unusual
systems) even just one byte. The important item is that there
are, and *must be*, two pointers -- the one named t, and one that
t points to -- before you can use **t. (The call to printf()
will access (*t)[0], aka **t, and then (*t)[1], and then (*t)[2],
and so on.)
Now, if you just use "foo" in a value context (or write &foo[0]),
the compiler will *construct* a pointer value, pointing to the
first element of the array:
foo:
+-----+-----+-----+-----+-...-+
*------> | 'b' | 'a' | 'r' | 0 | ... |
+-----+-----+-----+-----+-...-+
but this pointer is not (necessarily) stored in memory anywhere,
as it is a mere value, not an object. By adding "char *p = foo",
we create an actual object, so now the above becomes:
p: foo:
+----------+ +-----+-----+-----+-----+-...-+
| *------> | 'b' | 'a' | 'r' | 0 | ... |
+----------+ +-----+-----+-----+-----+-...-+
Now if we call f(&p), we pass to f() a value pointing to the pointer
named "p". f()'s first actions, even before any code inside f()
gets excuted, are to copy that value into an object, the one we
named "t" in f(). In other words, function parameters are really
just ordinary local variables, initialized "by magic" as we begin
executing the function, using the values passed in from the caller.
So now we have "t" (in f()) pointing to "p" (in the main() that I
snipped) pointing to &foo[0] (also in main()), so now the picture
we *wanted* -- t pointing to a pointer that points to the first of
a series of "char"s -- is in fact the picture we *have*.
Whenever you (the generic "you") are struggling with pointers, it
can help to draw pictures. Each named object (variable) is a box
containing a value, or junk if it is uninitialized. If the type
of the object is "pointer to ...", the object contains an arrow.
You need to make sure the arrow points in turn to some other thing
somewhere in memory -- another named object, or perhaps memory
obtained from malloc(). Each chunk of memory in turn contains a
value (or junk), and if the type it is meant to contain is "pointer
to ...", the value is an arrow -- and you have to make the arrow
point somewhere useful, just like last time. You can use a pointer
to write to the thing to which the pointer points, so one
arrow pointing to the first of several uninitialized-memory arrows
can be used to initialize them:
T **ptr = malloc(2 * sizeof *ptr);
produces (assuming malloc() succeeds) this picture:
(pointing off into the weeds)
ptr: /
+---------+ +----/---+---------+
| *---------------> | * | * |
+---------+ +--------+-----\---+
\ (more weeds)
and now you can say "ptr[0] = (some expression)" to set ptr[0],
and likewise with ptr[1]. As before, you can point them to
named variables (of type T), or call malloc() again. The
important thing is to make them point somewhere, and be sure
they still point somewhere valid whenever you use them.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it
http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.