Re: weird code.





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.

--
Eric.Sosman@xxxxxxx

.



Relevant Pages

  • Re: A couple of things from H&S
    ... expression of array type decays to a pointer to the array's first ... element *unless* it's in one of three contexts: the operand of sizeof, ... is quite obvious, p is the pointer. ...
    (comp.lang.c)
  • Re: [C or C++] Is this legal? sizeof *p
    ... where the size of an automatic array is defined at run time. ... > that case if sizeof is applied to a VLA, ... But applying sizeof to a VLA is applying ... > sizeof to an array, not a pointer, and using the name of an array as ...
    (alt.comp.lang.learn.c-cpp)
  • Re: How can I get the size of this?
    ... > I am now having a problem at using sizeof() function ... the pointer. ... Operating on something declared as an array returns the size of the ... LPCSTR is already typedef'd as "const char *", ...
    (microsoft.public.vc.language)
  • Re: Poll: SizeOf(variable) vs SizeOf(type), should SizeOf(variable)bebanned?
    ... Using SizeOf on variables does not prevent programming mistakes. ... How will you solve the problem for pointer variables? ... For that, I use dynamic arrays, which case I use Length in conjunction with SizeOf to determine the amount of memory occupied by the array data. ...
    (alt.comp.lang.borland-delphi)
  • Re: weird code.
    ... The variable data is a float pointer? ... "data" is a pointer to an array of 16384 elements of float. ... The parens ...
    (comp.lang.c)