471,319 Members | 1,579 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,319 software developers and data experts.

Array and binding question.

mdh
>From p112 ( K&R).
Given an array declared as
static char arr[2][13]= { { 0,1,........},{0,1,.....}};
let arr be passed as an argument to f.

f( int (*arr)[13] ) {....}

It is noted that the parentheses are necessary else it would be
interpreted as

int *arr[13] ( an array of 13 pointers to integers, as opposed to the
intended pointer to an array of 13 integers. The basis of this
explanation is that "[ ]" bind tighter than " * ".

Now, there have been extensive discussions about precedence and
associativity ....but my question is this.

RH has described precedence and associativity as deciding which
operators are associated with which operands.

In the case above, I assume the operator is the "[]", but what are
operands?
Or am I missing something else here...probably.

Thanks

Jul 31 '07 #1
18 1787
mdh <md**@comcast.netwrites:
>>From p112 ( K&R).
Given an array declared as
static char arr[2][13]= { { 0,1,........},{0,1,.....}};
let arr be passed as an argument to f.

f( int (*arr)[13] ) {....}

It is noted that the parentheses are necessary else it would be
interpreted as

int *arr[13] ( an array of 13 pointers to integers, as opposed to the
intended pointer to an array of 13 integers. The basis of this
explanation is that "[ ]" bind tighter than " * ".

Now, there have been extensive discussions about precedence and
associativity ....but my question is this.

RH has described precedence and associativity as deciding which
operators are associated with which operands.

In the case above, I assume the operator is the "[]", but what are
operands?
Or am I missing something else here...probably.
There are no operators and no operands, here, just syntax. The *, []
and ()s used in types are not operators operating on anything.

The reason (*x)[13] means what is does comes from the syntax rules of
C, but because these are very wordy, it is much easier to summarise
the effect of the syntax rules by saying things like "[] binds more
tightly that * in a type". You need to remember, though, that is just
a shorthand for the consequences of a formal grammar, written out in the
language specification.

The same is true, incidentally, for expressions. There is no operator
precedence table in the standard, just a grammar that says, for
example, that an addition can't be one of the parts of a
muliticative-expression, unless it is via the rule that allows a
cast-expression, which can be a unary-expression, which can be a
postfix-expression which can be a primary-expression, which can be an
expression in brackets! You can see why a summary tables is popular.

--
Ben.
Aug 1 '07 #2
mdh
On Jul 31, 5:36 pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
mdh <m...@comcast.netwrites:

f( int (*arr)[13] ) {....}
It is noted that the parentheses are necessary else it would be
interpreted as
int *arr[13] ......snip

There are no operators and no operands, here, just syntax. The *, []
and ()s used in types are not operators operating on anything.

The reason (*x)[13] means what is does comes from the syntax rules of
C, but because these are very wordy, it is much easier to summarise
the effect of the syntax rules by saying things like "[] binds more
tightly that * in a type". You need to remember, though, that is just
a shorthand for the consequences of a formal grammar, written out in the
language specification.
--
Ben.
Thanks...but may I ask this.
Accepting the rules as you described, could you perhaps explain why
one would mean

"a pointer to an array of 13 integers" -int (*arr)[13]

vs

"an array of 13 ptrs to integers" -int *arr[13].

I might be missing something quite basic here, hence the question.
Although the syntax and meaning of "binding" seem quite obvious, the
fact that I need to look it up each time, tells me I am missing
something.

thanks
Aug 1 '07 #3
mdh wrote:
On Jul 31, 5:36 pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
>mdh <m...@comcast.netwrites:
>>f( int (*arr)[13] ) {....}
It is noted that the parentheses are necessary else it would be
interpreted as
int *arr[13] ......snip


>There are no operators and no operands, here, just syntax. The *, []
and ()s used in types are not operators operating on anything.

The reason (*x)[13] means what is does comes from the syntax rules of
C, but because these are very wordy, it is much easier to summarise
the effect of the syntax rules by saying things like "[] binds more
tightly that * in a type". You need to remember, though, that is just
a shorthand for the consequences of a formal grammar, written out in the
language specification.
--
Ben.

Thanks...but may I ask this.
Accepting the rules as you described, could you perhaps explain why
one would mean

"a pointer to an array of 13 integers" -int (*arr)[13]

vs

"an array of 13 ptrs to integers" -int *arr[13].

I might be missing something quite basic here, hence the question.
Although the syntax and meaning of "binding" seem quite obvious, the
fact that I need to look it up each time, tells me I am missing
something.

thanks

I think the raw syntax for a pointer to an array (or a function pointer,
for that matter) is outright evil. If you need to look it up often, the
same perhaps applies to those who read your code... which means they won't.

To me, the salvation comes as typedef.
If
int a[13];
means array of 13 ints, then
typedef int atype[13];
defines atype as a type of array of 13 ints.
A pointer to an array of 13 ints is then of type atype*.
It is wordier but much more readable.

-- Ark
Aug 1 '07 #4
On Tue, 31 Jul 2007 18:20:07 -0700, mdh <md**@comcast.netwrote:
>On Jul 31, 5:36 pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
>mdh <m...@comcast.netwrites:
>
f( int (*arr)[13] ) {....}
It is noted that the parentheses are necessary else it would be
interpreted as
int *arr[13] ......snip


>There are no operators and no operands, here, just syntax. The *, []
and ()s used in types are not operators operating on anything.

The reason (*x)[13] means what is does comes from the syntax rules of
C, but because these are very wordy, it is much easier to summarise
the effect of the syntax rules by saying things like "[] binds more
tightly that * in a type". You need to remember, though, that is just
a shorthand for the consequences of a formal grammar, written out in the
language specification.
--
Ben.

Thanks...but may I ask this.
Accepting the rules as you described, could you perhaps explain why
one would mean

"a pointer to an array of 13 integers" -int (*arr)[13]

vs

"an array of 13 ptrs to integers" -int *arr[13].

I might be missing something quite basic here, hence the question.
Although the syntax and meaning of "binding" seem quite obvious, the
fact that I need to look it up each time, tells me I am missing
something.
It is the same as the difference between a+b*c and (a+b)*c.

If you take the precedence table on page 53 of K&R II at face value,
[] binds tighter than * so the expression int *arr[13] is treated the
same as int *(arr[13]). With these parentheses as a hint/crutch, the
difference from int (*arr)[13] should be clearer.
Remove del for email
Aug 1 '07 #5
mdh
On Jul 31, 9:34 pm, Barry Schwarz <schwa...@doezl.netwrote:
>
If you take the precedence table on page 53 of K&R II at face value,
[] binds tighter than * so the expression int *arr[13] is treated the
same as int *(arr[13]). With these parentheses as a hint/crutch, the
difference from int (*arr)[13] should be clearer.
Thanks ...nice explanation.

I also just found the FAQ and the footnote of the explanation.(http://
c-faq.com/aryptr/ptrary2.html) I think what I was missing as well was
that these are type declarations.... well, I hope they are. I also
think I was trying to make it more complicated than it deserves.
Strange how frequent puzzling issues turn up in the FAQ :-)

Thank you.

Aug 1 '07 #6
mdh
On Jul 31, 9:04 pm, Ark Khasin <akha...@macroexpressions.comwrote:
I think the raw syntax for a pointer to an array (or a function pointer,
for that matter) is outright evil. If you need to look it up often, the
same perhaps applies to those who read your code... which means they won't.

To me, the salvation comes as typedef.
Ah...salvation....for me ....lies in the next chapter of K&R!! :-)

Thanks for your input.

Aug 1 '07 #7
On Tue, 31 Jul 2007 18:20:07 -0700, mdh <md**@comcast.netwrote in
comp.lang.c:
On Jul 31, 5:36 pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
mdh <m...@comcast.netwrites:
>
f( int (*arr)[13] ) {....}
It is noted that the parentheses are necessary else it would be
interpreted as
int *arr[13] ......snip


There are no operators and no operands, here, just syntax. The *, []
and ()s used in types are not operators operating on anything.

The reason (*x)[13] means what is does comes from the syntax rules of
C, but because these are very wordy, it is much easier to summarise
the effect of the syntax rules by saying things like "[] binds more
tightly that * in a type". You need to remember, though, that is just
a shorthand for the consequences of a formal grammar, written out in the
language specification.
--
Ben.

Thanks...but may I ask this.
Accepting the rules as you described, could you perhaps explain why
one would mean

"a pointer to an array of 13 integers" -int (*arr)[13]

vs

"an array of 13 ptrs to integers" -int *arr[13].

I might be missing something quite basic here, hence the question.
Although the syntax and meaning of "binding" seem quite obvious, the
fact that I need to look it up each time, tells me I am missing
something.

thanks
In this case, binding defines what "attributes" are applied to the
identifier first. I put "attributes" in quotation marks because it is
not a word defined in the standard, but one I think might be useful
here.

In the declaration:

int *arr[13]

....the tighter binding of [] means that [] is applied to "arr" first:

arr[/*anything*/] means "arr is an array"

arr[13] means "arr is an array of 13 ?"

*arr[13] means "arr is an array of 13 pointers"

int *arr[13] means "arr is an array of 13 pointers to int"

In the declaration:

int (*arr)[13]

....the parentheses enforce a grouping, all elements inside the
parentheses are applied before anything outside the parentheses, so:

(*arr) means "arr is a pointer"

(*arr)[/*anything*/] means "arr is a pointer to an array"

(*arr)[13] means "arr is a pointer to an array of 13 ?"

int (*arr)[13] means "arr is a pointer to an array of 13 ints"

Note that there is a rule of thumb that you can use that holds in
many, but not all cases, the "right-left" rule. It is based on the
fact that in most cases, postfix operators (on the right) bind more
tightly prefix operators (on the left).

That is why:

*char_ptr++;

....increments the pointer, and not what it points to, because the
postfix ++ operator binds more tightly than the prefix pointer
indirection operator.

If you actually want to increment the character pointed to, and not
the pointer, you would need to do:

(*char_ptr)++;

In the absence of parentheses, you start at the identifier (object,
function, or typedef name), and start looking to the right. One you
have found the "attribute" on the right, go left. And, if necessary,
back-and-forth right-to-left as necessary.

If you look back at the way I stepped through int *arr[13], you can
see the application of the right-left rule.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
Aug 1 '07 #8
mdh wrote:
From p112 ( K&R).
Given an array declared as
static char arr[2][13]= { { 0,1,........},{0,1,.....}};
let arr be passed as an argument to f.

f( int (*arr)[13] ) {....}

It is noted that the parentheses are necessary else it would be
interpreted as

int *arr[13] ( an array of 13 pointers to integers, as opposed to the
intended pointer to an array of 13 integers. The basis of this
explanation is that "[ ]" bind tighter than " * ".
In the case of a function parameter (as you have), that's not the case.
It's actually the same as int *arr[], which is the same as int **arr.

Brian
Aug 1 '07 #9
"Default User" <de***********@yahoo.comwrites:
mdh wrote:
From p112 ( K&R).
Given an array declared as
static char arr[2][13]= { { 0,1,........},{0,1,.....}};
let arr be passed as an argument to f.

f( int (*arr)[13] ) {....}

It is noted that the parentheses are necessary else it would be
interpreted as

int *arr[13] ( an array of 13 pointers to integers, as opposed to the
intended pointer to an array of 13 integers. The basis of this
explanation is that "[ ]" bind tighter than " * ".

In the case of a function parameter (as you have), that's not the case.
It's actually the same as int *arr[], which is the same as int
**arr.
As a parameter 'int *arr[]' is indeed the same 'int **arr' but, even
as a parameter 'int (*arr)[13]' is only the same as 'int arr[][13]'
(and parenthesised versions of the same like 'int (arr[])[13]'). It
is quite different to 'int **arr'.

The parse is crucial to determining the meaning since 'int (*arr)[13]'
and 'int *arr[13]' are, as the OP states, quite different parameter
types.

--
Ben.
Aug 1 '07 #10
On Jul 31, 8:20 pm, mdh <m...@comcast.netwrote:
On Jul 31, 5:36 pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:


mdh <m...@comcast.netwrites:
f( int (*arr)[13] ) {....}
It is noted that the parentheses are necessary else it would be
interpreted as
int *arr[13] ......snip
There are no operators and no operands, here, just syntax. The *, []
and ()s used in types are not operators operating on anything.
The reason (*x)[13] means what is does comes from the syntax rules of
C, but because these are very wordy, it is much easier to summarise
the effect of the syntax rules by saying things like "[] binds more
tightly that * in a type". You need to remember, though, that is just
a shorthand for the consequences of a formal grammar, written out in the
language specification.
--
Ben.

Thanks...but may I ask this.
Accepting the rules as you described, could you perhaps explain why
one would mean

"a pointer to an array of 13 integers" -int (*arr)[13]

vs

"an array of 13 ptrs to integers" -int *arr[13].

I might be missing something quite basic here, hence the question.
Although the syntax and meaning of "binding" seem quite obvious, the
fact that I need to look it up each time, tells me I am missing
something.

thanks
Probably the best way to answer this question is to walk through the
grammar for each declaration (I'm using the grammar from Harbison &
Steele, 5th ed., but the grammar in K&R should be similar). I'll use
uppercase to identify non-terminal symbols. The following chart is
best viewed with a fixed-width font (and hopefully Google Groups won't
munge it beyond all hope).

In each case we start with the non-terminal symbol DECLARATION.
Remember that the compiler scans left-to-right, and tries to build the
longest valid tokens that it can. So in a declaration, the first
thing we see is the type specifier "int". Following the type
specifier is one or more declarators. Declarators serve two purposes
-- they introduce the name of the symbol being defined, as well as
providing additional type information. The presence of the '*' token
in a declarator indicates that the declared symbol is of type "pointer-
to" something, whereas the subscript tokens '[' and ']' indicate that
the symbol is of type "array-of" something.

int (*arr)[13]

DECLARATION
/ \
DECLARATION-SPECIFIERS INITIALIZED-DECLARATOR-LIST
| |
TYPE-SPECIFIER INITIALIZED-DECLARATOR
| |
SIGNED-TYPE-SPECIFIER DECLARATOR
| |
int DIRECT-DECLARATOR
|
ARRAY-DECLARATOR
/ \
DIRECT-DECLARATOR '[' CONSTANT-EXPRESSION ']'
| |
'(' DECLARATOR ')' 13
|
POINTER-DECLARATOR
/ \
'*' DIRECT-DECLARATOR
|
SIMPLE-DECLARATOR
|
IDENTIFIER
|
arr

As you can see from this evaluation tree, the presence of the
parentheses in the declarator causes the '*' token to be more closely
associated with the symbol 'arr' than the subscript tokens. That
means the "pointer-to" type information is applied to arr before the
"array-of" type information -- hence, "int *(arr)[13]" evaluates to
"pointer to 13-element array of int".

Now let's look at the other declaration:

int *arr[13]

DECLARATION
/ \
DECLARATION-SPECIFIERS INITIALIZED-DECLARATOR-LIST
| |
TYPE-SPECIFIER INITIALIZED-DECLARATOR
| |
SIGNED-TYPE-SPECIFIER DECLARATOR
| |
int POINTER-DECLARATOR
/ \
POINTER DIRECT-DECLARATOR
| |
'*' ARRAY-DECLARATOR
/ \
DIRECT-DECLARATOR '[' CONSTANT-EXPRESSION
']'
| |
SIMPLE-DECLARATOR 13
|
IDENTIFIER
|
arr

In this case, the subscript tokens are more closely associated with
the symbol arr than the '*' token, so the "array-of" type information
is applied before the "pointer-to" type information, so the
declaration reads as "13-element array of pointers to int."

Hopefully that made sense (and was close to right).

Aug 1 '07 #11
On Aug 1, 5:24 pm, John Bode <john_b...@my-deja.comwrote:

[snip]
"array-of" type information -- hence, "int *(arr)[13]" evaluates to
"pointer to 13-element array of int".
[snip]

Argh -- of course, "*(arr)[13]" should be written "(*arr)[13]".

Grump.

Aug 1 '07 #12
Ben Bacarisse wrote:
"Default User" <de***********@yahoo.comwrites:
mdh wrote:
From p112 ( K&R).
Given an array declared as
static char arr[2][13]= { { 0,1,........},{0,1,.....}};
let arr be passed as an argument to f.

f( int (*arr)[13] ) {....}

It is noted that the parentheses are necessary else it would be
interpreted as

int *arr[13] ( an array of 13 pointers to integers, as opposed to
the >intended pointer to an array of 13 integers. The basis of this
explanation is that "[ ]" bind tighter than " * ".
In the case of a function parameter (as you have), that's not the
case. It's actually the same as int *arr[], which is the same as
int **arr.

As a parameter 'int *arr[]' is indeed the same 'int **arr' but, even
as a parameter 'int (*arr)[13]' is only the same as 'int arr[][13]'
(and parenthesised versions of the same like 'int (arr[])[13]'). It
is quite different to 'int **arr'.
Did anyone say any differently?
The parse is crucial to determining the meaning since 'int (*arr)[13]'
and 'int *arr[13]' are, as the OP states, quite different parameter
types.
The second is not, in the example give, the type the OP stated.


Brian
Aug 1 '07 #13
"Default User" <de***********@yahoo.comwrites:
Ben Bacarisse wrote:
>"Default User" <de***********@yahoo.comwrites:
mdh wrote:

From p112 ( K&R).
Given an array declared as
static char arr[2][13]= { { 0,1,........},{0,1,.....}};
let arr be passed as an argument to f.

f( int (*arr)[13] ) {....}

It is noted that the parentheses are necessary else it would be
interpreted as

int *arr[13] ( an array of 13 pointers to integers, as opposed to
the >intended pointer to an array of 13 integers. The basis of this
>explanation is that "[ ]" bind tighter than " * ".

In the case of a function parameter (as you have), that's not the
case. It's actually the same as int *arr[], which is the same as
int **arr.

As a parameter 'int *arr[]' is indeed the same 'int **arr' but, even
as a parameter 'int (*arr)[13]' is only the same as 'int arr[][13]'
(and parenthesised versions of the same like 'int (arr[])[13]'). It
is quite different to 'int **arr'.

Did anyone say any differently?
Well, I thought you did but obviously I am mistaken! Sorry.

To what did your "it" refer in "It's actually the same as int *arr[]"?
I thought you were referring to one of the OP's two readings of his
type 'int (*arr)[13]'.

--
Ben.
Aug 2 '07 #14
Ben Bacarisse wrote:
"Default User" <de***********@yahoo.comwrites:
As a parameter 'int *arr[]' is indeed the same 'int **arr'
Did anyone say any differently?

Well, I thought you did but obviously I am mistaken! Sorry.

To what did your "it" refer in "It's actually the same as int *arr[]"?
I thought you were referring to one of the OP's two readings of his
type 'int (*arr)[13]'.
Here's what the OP said:

================================================== ==========
let arr be passed as an argument to f.

f( int (*arr)[13] ) {....}

It is noted that the parentheses are necessary else it would be
interpreted as

int *arr[13] ( an array of 13 pointers to integers, as opposed to the
intended pointer to an array of 13 integers. The basis of this
explanation is that "[ ]" bind tighter than " * ".

================================================== ==========

Brian

Brian
Aug 2 '07 #15
"Default User" <de***********@yahoo.comwrites:
Ben Bacarisse wrote:
>"Default User" <de***********@yahoo.comwrites:
>As a parameter 'int *arr[]' is indeed the same 'int **arr'
Did anyone say any differently?

Well, I thought you did but obviously I am mistaken! Sorry.

To what did your "it" refer in "It's actually the same as int *arr[]"?
I thought you were referring to one of the OP's two readings of his
type 'int (*arr)[13]'.

Here's what the OP said:

================================================== ==========
let arr be passed as an argument to f.

f( int (*arr)[13] ) {....}

It is noted that the parentheses are necessary else it would be
interpreted as

int *arr[13] ( an array of 13 pointers to integers, as opposed to the
intended pointer to an array of 13 integers. The basis of this
explanation is that "[ ]" bind tighter than " * ".

================================================== ==========
Ah, right. I hope you can see the source of my confusion. The text
you commented on also used "it" ("it [the form with parentheses] would
be...") and so when you then went on to talk about "it", the natural
reading (at least in *my* head) was that your "it" referred to the
original "it"!

Sorry for the confusion.

--
Ben.
Aug 2 '07 #16
Ben Bacarisse wrote:
"Default User" <de***********@yahoo.comwrites:
Here's what the OP said:

================================================== ==========
let arr be passed as an argument to f.

f( int (*arr)[13] ) {....}

It is noted that the parentheses are necessary else it would be
interpreted as

int *arr[13] ( an array of 13 pointers to integers, as opposed to
the intended pointer to an array of 13 integers. The basis of this
explanation is that "[ ]" bind tighter than " * ".

================================================== ==========

Ah, right. I hope you can see the source of my confusion. The text
you commented on also used "it" ("it [the form with parentheses] would
be...") and so when you then went on to talk about "it", the natural
reading (at least in my head) was that your "it" referred to the
original "it"!

Sorry for the confusion.

Not a problem, the messages tended to be somewhat confusing. I tried to
straighten out one point of what seemed to me to confusion, but I feel
I only muddied the waters further.

Brian
Aug 2 '07 #17
mdh
On Aug 1, 8:50 am, Jack Klein <jackkl...@spamcop.netwrote:
On Tue, 31 Jul 2007 18:20:07 -0700, mdh <m...@comcast.netwrote in
In the declaration:

int *arr[13]

...the tighter binding of [] means that [] is applied to "arr" first:

arr[/*anything*/] means "arr is an array"

arr[13] means "arr is an array of 13 ?"

*arr[13] means "arr is an array of 13 pointers"

int *arr[13] means "arr is an array of 13 pointers to int"

In the declaration:

int (*arr)[13]

...the parentheses enforce a grouping, all elements inside the
parentheses are applied before anything outside the parentheses, so:

(*arr) means "arr is a pointer"

(*arr)[/*anything*/] means "arr is a pointer to an array"

(*arr)[13] means "arr is a pointer to an array of 13 ?"

int (*arr)[13] means "arr is a pointer to an array of 13 ints"

Note that there is a rule of thumb that you can use that holds in
many, but not all cases, the "right-left" rule. It is based on the
fact that in most cases, postfix operators (on the right) bind more
tightly prefix operators (on the left).
Thank you very much for that great explanation....

Aug 2 '07 #18
mdh
On Aug 1, 3:24 pm, John Bode <john_b...@my-deja.comwrote:
>eclaration reads as "13-element array of pointers to int."

Hopefully that made sense (and was close to right).

Thanks for all that effort...it certainly illuminates Ben Bacarisse's
point about rules of syntax. It will become part of my permanent C
notes.
Aug 2 '07 #19

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

7 posts views Thread by Jed | last post: by
4 posts views Thread by Jim Shaffer | last post: by
4 posts views Thread by JonathanG | last post: by
26 posts views Thread by aruna.mysore | last post: by
reply views Thread by rosydwin | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.