* and -> operator syntax

E

Emanuele Blanco

We all know that p->item is the most common syntax for (*p).item (or am I
wrong ? ^^). However, if p isn't a struct * but a struct **, what's the
correct way to choose a member of the double-pointed structure ? I guess
(*p)->item, but I wonder if writing *p->item is the same thing. What's the
precedence in this case ? Thanks in advance.
 
C

Christopher Benson-Manica

Emanuele Blanco said:
We all know that p->item is the most common syntax for (*p).item (or am I
wrong ? ^^). However, if p isn't a struct * but a struct **, what's the
correct way to choose a member of the double-pointed structure ? I guess
(*p)->item, but I wonder if writing *p->item is the same thing. What's the
precedence in this case ? Thanks in advance.

Your friendly C book (which hopefully is K&R) should have a convenient
table showing the precedence of operators. In any case, postfix
operators (such as ->) have higher precedence than prefix operators (such
as *), so *p->item is equivalent to *(p->item), which is not the same
thing as (*p)->item. HTH.
 
D

Default User

Emanuele said:
We all know that p->item is the most common syntax for (*p).item (or am I
wrong ? ^^). However, if p isn't a struct * but a struct **, what's the
correct way to choose a member of the double-pointed structure ? I guess
(*p)->item, but I wonder if writing *p->item is the same thing. What's the
precedence in this case ? Thanks in advance.


No, it's not. -> has higher precedence than * so the dereference is
applied to the structure member. As p is a pointer to pointer, the
member operator is illegal. Use the first method.




Brian Rodenborn
 
C

Christopher Benson-Manica

Christopher Benson-Manica said:
Your friendly C book (which hopefully is K&R) should have a convenient
table showing the precedence of operators. In any case, postfix
operators (such as ->) have higher precedence than prefix operators (such
as *), so *p->item is equivalent to *(p->item), which is not the same
^^^^^^^
As Brian noted, this is a syntax error; I didn't see it, or I would
have pointed it out...
 
B

Ben Pfaff

Christopher Benson-Manica said:
^^^^^^^
As Brian noted, this is a syntax error; I didn't see it, or I would
have pointed it out...

It's not a syntax error, it's semantically invalid given your
assumptions. Given other assumptions, it's a perfectly valid
expression. If it were a syntax error, then it wouldn't parse
into a valid syntax tree in the grammar given in the standard,
but in fact it does.
 
C

Christopher Benson-Manica

Ben Pfaff said:
It's not a syntax error, it's semantically invalid given your
assumptions. Given other assumptions, it's a perfectly valid
expression. If it were a syntax error, then it wouldn't parse
into a valid syntax tree in the grammar given in the standard,
but in fact it does.

Right, I stand (humbly) corrected. Thanks.
 
N

Nils Petter Vaskinn

Emanuele Blanco <[email protected]> spoke thus:
[...]
I guess
(*p)->item, but I wonder if writing *p->item is the same thing. What's the
precedence in this case ?
[...]

postfix
operators (such as ->) have higher precedence than prefix operators (such
as *), so *p->item is equivalent to *(p->item), which is not the same
thing as (*p)->item. HTH.

So again the rule applies; "When in doubt use parenthesis". If you
(OP) have to look up the precedence rules we can assume that there are
oter people (that may work with that code) that might have to look it up
too (Unless they ($DEITY forbid) make the wrong assumption about what the
code does.) Slapping () in there even in cases where they are redundant
may remove any doubt about what an expression means, just don't overdo it.
 
J

Joe Wright

Emanuele said:
We all know that p->item is the most common syntax for (*p).item (or am I
wrong ? ^^). However, if p isn't a struct * but a struct **, what's the
correct way to choose a member of the double-pointed structure ? I guess
(*p)->item, but I wonder if writing *p->item is the same thing. What's the
precedence in this case ? Thanks in advance.

#define N 10
typedef struct st {
int a;
int b;
} st;

st **p;
int i;

p = malloc(N * sizeof *p);
for (i = 0; i < N; ++i) {
p = malloc(sizeof (st));
}

So now p[n] points to one of 10 structures. *p[n] is the structure.
p[5]->a is an int. (*p[5]).a is the same int.
 
C

Chris Torek

(This is typical, yes. Also, if you intend to use (*p) a lot, you
might load it into another variable first, then just write q->item.)

So now p[n] points to one of 10 structures. *p[n] is the structure.
p[5]->a is an int. (*p[5]).a is the same int.

It is also worth adding that *p and p[0] are synonymous:

int *ip;
...
*ip = 3;
ip[0] = 3; /* same meaning */

Hence p->a can always be rewritten as p[0].a:

struct S *p;
...
p->a = 3;
p[0].a = 3;

Since *p and p[0] mean the same thing, if we have a pointer that
points to a pointer:

struct S **pp;

then pp[0] is the pointer at (*pp), and pp[0][0] is the pointer
at (*(*pp)). Thus all three of these are equivalent:

(*pp)->a = 3;
pp[0]->a = 3;
pp[0][0].a = 3;
 

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,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top