Re: weird code.



Wow. I am thourghly impressed Eric (and the other replies). I have
never seen this kind of declaration ever. And I am an
intermediate/advanced programmer I my opinion.

Your command of the C language is spot on... especially when you were
quoting the precedence rule.

------

I suppose the last question is this. How does sizeof(data[0]) know
that it is a `pointer to 16384 floats' ?

I guess it is the compiler knows this and does the leg work to replace
the data[0] with sizeof(16384*float), right?

------

In regards to no comments:
Unfortunately, there are no comments because ... well that *seems* to
be a trend in this company that I work at (they expect you to know
everything and be a genius).


Eric Sosman wrote:
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: Help a beginner - function with pointer ...
    ... i thought (float *) T would be appealing to ... The result is the value obtained by converting the ... `T' refers to a one-dimensional array whose elements are also ... using a pointer to the array's first element. ...
    (comp.lang.c)
  • Re: new foo[42]
    ... > First question: ... 42 type 'float' objects, and returns the address ... value in the pointer object 'foo'. ... The first form above dynamically allocates an array (which ...
    (comp.lang.cpp)
  • Re: weird code.
    ... The variable data is a float pointer? ... array of 16384 float objects. ... We just write `sizeof *data' and the compiler (knowing what ...
    (comp.lang.c)
  • Re: getopt in linux
    ... > pointer to an array of pointers to char, ... The second parameter is declared as an array of pointer to ... char, but is immediately converted to a pointer to pointer to char. ... The declaration of the parameter is converted from "array of pointer to ...
    (comp.unix.programmer)
  • Re: Problem with event declaration - possible VS.NET bug?
    ... when I modified the event declaration to ... The difference is the code without errors is only passing ... > a pointer to a pointer to the array. ...
    (microsoft.public.dotnet.languages.vc)