Yossarian said:
Hi,
I'm a bit confused about something, hopefully someone can put me
straight.
I'd like to be able to call a function which takes a pointer to
pointer, have that function allocate memory and return the size. I
can't get it to work and I would like to know why this code outputs
wierd values (the first mem address is ok i think):
int f3(int **ptr)
{
*ptr = malloc(sizeof(int)*4);
If the malloc() call succeeds, you now have this situation
(apologies for the bad ASCII art):
ptr p2 dynamic
+------+ +------+ +---+---+---+---+
| *--------> | *--------> |int|int|int|int|
+------+ +------+ +---+---+---+---+
(Side-issue: This isn't quite right. The "%p" specifier
requires a `void*' pointer value, and you're giving it an
`int*' instead. On many machines you will get away with this
error, but for correctness write `(void*)*ptr' instead.)
Here's the crux: I don't think you understand what this
statement accomplishes. It says "Fetch the value at `*ptr'
(the contents of the second box above), ignore them, and
then advance `ptr' itself by one `int*' position." Now you
have
ptr p2 dynamic
+------+ +------+ +---+---+---+---+
| *-----+ | *--------> |int|int|int|int|
+------+ | +------+ +---+---+---+---+
|
+-->
You are now in a serious state of error. You are trying
to print the value `ptr' points at, but it no longer points
at anything useful. It is legal to form a "one past the end"
pointer, but it is not legal to try to access the memory at
that position. There might not even *be* any memory at that
position, and even if there is you have never stored a value
there. So when you try to access the uninitialized value in
a region of memory that might not even exist, all bets are
off and anything at all might happen.
"Fetch the pointed-to value, ignore it, and advance `ptr'
again." Once again you commit the error of fetching a value
that hasn't been initialized and might not even exist, and
then you add a new error: A "one past the end" pointer is
legal, but a "two past the end" pointer is not. Things just
get worse.
printf("%p\n", *ptr);
}
int main(void)
{
int *p2;
f3(&p2);
return 0;
}
The output is:
0xa040448
0x0
0x22f40
As I hope you now understand, the fact that you got any
output at all is more by good luck than good management. I
suggest you review Question 4.3 in the comp.lang.c Frequently
Asked Questions (FAQ) list
http://www.eskimo.com/~scs/C-faq/top.html
In fact, reviewing all of Sections 4, 6, and 7 might be a
good idea.