syn1kk wrote On 08/23/06 13:55,:
1: float (*data)[16384];
2: data = malloc(31 * sizeof(data[0]));
3: data[i][j] = VARIABLE;
Question 1: The variable data is a float pointer?
No, it is a float[16384] pointer. The "thing" that `data'
points to (when it's made to point to something) will be an
array of 16384 float objects. (See below.)
Question 2: When the [16384] is used. Does that mean it is an array of
float pointers? What does it mean?
An array of float pointers would be `float *data[16384];',
without the parentheses. Remember the "declaration mimics use"
rule (everybody scratches his head over it eventually). In the
no-parentheses case, the declaration says that an expression of
the form `*data[i]' is a float. Looking at your handy C operator
precedence table you'll find that [] "binds more tightly than" *,
so `*data[i]' means the same thing as `*(data[i])'. This says
to fetch the i'th element of the array, and then to use that
element as a pointer. That process must produce a float, so by
reasoning backwards we find that data[i] must be a pointer to
float, and that data itself must be an array of such pointers.
... but that's not what your puzzling code says; it's got
some parentheses that change the meaning. Let's walk through
the actual code in the same way we just did in the previous
paragraph -- we've had some practice, so by now we ought to
be pretty good at this, right?
`float (*data)[16384];' says that an expression of the
form `(*data)[i]' is a float. This time we don't need to look
for our precedence table, because the parentheses have already
shown us what bits go with what. The expression says to use
`data' as a pointer to -- well, let's just say "something"
for the moment. Once we've got the "something," the `[i]'
bit means to treat it as an array and get the i'th element.
That element must be a float, so we reason backwards as before:
if "something"[i] is a float, then "something" must be an
array of float. If *data is a "something", then `data' must
be a pointer to "something," that is, a pointer to an array
of float.
Pointer to array != array of pointers.
Question 3: Or does it mean that there are 16384 floats allocated with
the pointer data that points to the head of those 16384 floats?
I *think* the answer is "Yes," but I'm not entirely sure
of what your question is. (See above.)
Question 4: It will malloc 31*16384 floats... I assume this is true
based on how the program uses it. But shouldn't it be mallocing
31*sizeof(float*)?
The first part is right, but it might be more instructive
to phrase it a little differently: malloc() is being asked for
enough memory for 31 "somethings," where each "something" is
an array of 16384 floats. That's 31*16384 floats in all, as
you say, and malloc() knows only the total size and nothing
about how the memory will be subdivided, so there's really no
difference. But if *you* pay attention to the subdivisions,
you may have an easier time sorting out code like this.
Rule: If `p' is a pointer to any object type, any type
whatever, then `sizeof *p' is the amount of memory required
to store one instance of that type. Always.
Let's apply the rule: We know that `data' points to a
kind of object, namely, an array of 16384 floats. How much
memory would such an array require? We could calculate it
as `16384 * sizeof(float)', but we could calculate it more
conveniently as `sizeof *data' (or `sizeof data[0]'). Why is
this more convenient? Because we'll never slip up and write
`sizeof(float*)' when we should have written `sizeof(float)',
or `sizeof(struct msghead)' instead of `sizeof(struct msgbody)'.
We just write `sizeof *data' and the compiler (knowing what
`data' points to) fills in the correct number for us, reducing
our chance of making a silly error.
If `sizeof data[0]' is the amount of room needed for one
"something," how much do we need for thirty-one of them?
`31 * sizeof data[0]', obviously. Again, we could have written
`31 * 16384 * sizeof(float)', but again it's more convenient
and less error-prone to let the compiler do the work.
Question 5: Then the code starts using data as a multidimensional
array. When did it become a multidimensional array?! and how did it
become multidimensional?!
When you've got a pointer to something, you can treat that
pointer as the start of an array of those somethings, right?
Given `char *p = "Hello";' you can write p[0], p[1], and so
on to refer to the 'H', the 'e', and so on. Clear?
Okay: `data' is a pointer to something, and we've requested
space for thirty-one of those somethings. So each of data[0],
data[1], ..., data[30] is one of the somethings, right?
And each of those somethings is an array of 16384 floats.
What can you do with an array? You can use a subscript to get
at one of its elements. So if data[3] is an array of 16384
floats, then data[3][42] is one of those floats.
Hope this helps. You're not alone in being confused by
this; there's at least one "regular" on this newsgroup who's
failed to understand it.
--
Er*********@sun.com