weird code.

S

syn1kk

1: float (*data)[16384];
2: data = malloc(31 * sizeof(data[0]));
3: data[j] = VARIABLE;

Question 1: The variable data is a float pointer?

Question 2: When the [16384] is used. Does that mean it is an array of
float pointers? What does it mean?

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?

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*)?

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?!
 
G

Guest

syn1kk said:
1: float (*data)[16384];
2: data = malloc(31 * sizeof(data[0]));
3: data[j] = VARIABLE;

Question 1: The variable data is a float pointer?

Question 2: When the [16384] is used. Does that mean it is an array of
float pointers? What does it mean?

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?

data is a pointer to an array of 16384 floats.
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*)?
Given it's a pointer to an array, you don't want 31 float*.
31 arrays of 16384 floats, sure.
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?!
'data' is a pointer to an array. You've allocated room for 31
such arrays, so data[0] is the 1. array of 16384 floats,
data[1] the next array, and so on.
 
J

jmcgill

syn1kk said:
1: float (*data)[16384];
2: data = malloc(31 * sizeof(data[0]));
3: data[j] = VARIABLE;

Question 1: The variable data is a float pointer?


"data" is a pointer to an array of 16384 elements of float. The parens
are unnecessary.
Question 2: When the [16384] is used. Does that mean it is an array of
float pointers? What does it mean?

"data" is a pointer to an array of 16384 elements of float.
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?

"data" is a pointer to an array of 16384 elements of float.
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*)?

There are a lot of things that "should be" in this code, beginning with
a few hundred words of comments where the programmer can explain
himself. He does have some explaining to do.
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?!

There's nothing magical about the array notation. It's just another way
of expressing an offset from your pointer.
 
E

Eric Sosman

syn1kk wrote On 08/23/06 13:55,:
1: float (*data)[16384];
2: data = malloc(31 * sizeof(data[0]));
3: data[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' is a float. Looking at your handy C operator
precedence table you'll find that [] "binds more tightly than" *,
so `*data' means the same thing as `*(data)'. 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 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)' 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 `'
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" 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.
 
B

Bill Pursell

jmcgill said:
syn1kk said:
1: float (*data)[16384];
2: data = malloc(31 * sizeof(data[0]));
3: data[j] = VARIABLE;

Question 1: The variable data is a float pointer?


"data" is a pointer to an array of 16384 elements of float. The parens
are unnecessary.


The parentheses are completely necessary. With them, data is
a pointer to an array of 16384 floats. Without them, data is
an array of 16384 pointers.

For example:
#include <stdio.h>
#include <stdlib.h>

int
main(void)
{

float (*data0)[16384];
float *data1[16384];

printf("size of data0 is: %d\n", sizeof data0);
printf("size of data1 is: %d\n", sizeof data1);
return EXIT_SUCCESS;
}


[tmp]$ ./a.out
size of data0 is: 4
size of data1 is: 65536
[tmp]$
 
S

syn1kk

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 said:
syn1kk wrote On 08/23/06 13:55,:
1: float (*data)[16384];
2: data = malloc(31 * sizeof(data[0]));
3: data[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' is a float. Looking at your handy C operator
precedence table you'll find that [] "binds more tightly than" *,
so `*data' means the same thing as `*(data)'. 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 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)' 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 `'
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" 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.
 
B

Bill Pursell

syn1kk said:
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.

Because you declared it that way. :)
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).

Buck the trend. Failing to write comments is not the mark
of a genius...it is the mark of someone who boosts his/her
ego by seeing other people struggle through
obfuscated crap which they have created, and take
pleasure in thinking that their ability to produce such
garbage is somehow a mark of skill. Remember
that verbosity is often just as bad as excessive
brevity (often worse), and merely commenting code
is not sufficient. Code should be clear. Achieving
clarity often requires subtle (or fundamental) rethinking
of a design that generally leads to more efficient code.
Comments are key, but they are not sufficient and they
are not always appropriate. However, the general idea that
"comments are for the weak" is a myth perpetrated
by ignorant baboons.
 
J

jmcgill

Bill said:
The parentheses are completely necessary.

I'll take your word for that, but my cdecl parses it the same with or
without the parens.

Not that I'd ever write a declaration like this, unless it was
absolutely necessary.
 
J

jmcgill

syn1kk said:
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).

"Maybe your genius will be better appreciated at your next job."
 
B

Barry Schwarz

I'll take your word for that, but my cdecl parses it the same with or
without the parens.

Then you need to find one that works correctly.
Not that I'd ever write a declaration like this, unless it was
absolutely necessary.


Remove del for email
 
D

Dik T. Winter

>
> I'll take your word for that, but my cdecl parses it the same with or
> without the parens.

cdecl> explain float (*data)[16384];
declare data as pointer to array 16384 of float
cdecl> explain float *data[16384];
declare data as array 16384 of pointer to float
cdecl>

What does yours give?
 
J

jmcgill

Dik said:
I'll take your word for that, but my cdecl parses it the same with or
without the parens.

cdecl> explain float (*data)[16384];
declare data as pointer to array 16384 of float
cdecl> explain float *data[16384];
declare data as array 16384 of pointer to float
cdecl>

What does yours give?

It says I need to get more than 3 or 4 hours of sleep. Apologies, and
especially apologies to the o.p.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,270
Latest member
TopCryptoTwitterChannels_

Latest Threads

Top