LWN.net Logo

Grokking convoluted expressions

Grokking convoluted expressions

Posted Mar 16, 2007 10:31 UTC (Fri) by nix (subscriber, #2304)
In reply to: Grokking convoluted expressions by ldo
Parent article: Quotes of the week

I don't know, I've never seen anything quite like it. Operator mangling like that is fairly unusual in C because nobody can remember the precedence rules :)


(Log in to post comments)

Grokking convoluted expressions

Posted Mar 17, 2007 12:58 UTC (Sat) by Tet (subscriber, #5433) [Link]

I thought everyone knew the rules for operator precedence in C and C-like languages: * and / bind more tightly than + and -, and everything else gets parentheses :-)

(My Google-fu is letting me down, and I can't find the original author of that quote)

Grokking convoluted expressions

Posted Mar 17, 2007 16:28 UTC (Sat) by nix (subscriber, #2304) [Link]

Yeah, exactly. It really gets confusing when *, ->, [], &, &&, and
arithmetic operators all come and play together.

Grokking convoluted expressions

Posted Mar 17, 2007 18:38 UTC (Sat) by tjc (subscriber, #137) [Link]

It really gets confusing when *, ->, [], [snip] and arithmetic operators all come and play together.
Things would be simpler if *, both as a pointer declarator and as the dereference operator, were postfix (and as a consequence left-to-right associative, with the precedence level incremented by one). It looks weird, but that's mostly because we're not use to seeing it that way. It would be also consistent with the use of [].

For example, the signal function would then be:

void signal(int signum, void handler*(int)) *(int);

...which is a bit easier to untangle than the way it really is:

void (*signal(int signum, void (*handler)(int))) (int);

That would also eliminate the need for ->, since one could just do this:

foo*.bar

...which is consistent with:

foo[0].bar

Of course there's no need for -> anyway, since there's no ambiquity between struct_var.foo and pointer_var.foo -- taking the member of a pointer doesn't make sense, so there's no need for a special operator. The compiler could just take care of this for us.

It's probably too late to change. :-)

Grokking convoluted expressions

Posted Mar 18, 2007 1:53 UTC (Sun) by nix (subscriber, #2304) [Link]

This is of course exactly what Pascal, Ada and other related languages do
with ^. It *does* make more sense than the alternatives, but there's no
chance of changing now :( hell, the precedence rules couldn't be changed
when C was less than three years old (when && and || were introduced...
with the wrong precedences for compatibility reasons), so I doubt a whole
new operator could be introduced now :)

Grokking convoluted expressions

Posted Mar 24, 2007 5:21 UTC (Sat) by RareCactus (guest, #41198) [Link]

Of course there's no need for -> anyway, since there's no ambiquity between struct_var.foo and pointer_var.foo -- taking the member of a pointer doesn't make sense, so there's no need for a special operator. The compiler could just take care of this for us.

It's probably too late to change. :-)

Having the language infer what you mean to do by the context is often a bad idea. If people want to dereference a pointer, they should use the dereference operator, not just silently have the language fill that in.

And yes, the syntax of function pointers is fubar in C.

Grokking convoluted expressions

Posted Mar 17, 2007 22:38 UTC (Sat) by ldo (subscriber, #40946) [Link]

Operator mangling like that is fairly unusual in C because nobody can remember the precedence rules :)

Yeah, that's why I included the parenthesis-riddled version.

But then, why do you need to remember? I keep a copy of K&R 2nd ed where I can reach it without leaving this chair, just so I can look up finer points like this.

For everybody else, I've put together this page. :)

Grokking convoluted expressions

Posted Mar 19, 2007 15:03 UTC (Mon) by tjc (subscriber, #137) [Link]

For everybody else, I've put together this page. :)
A very useful page, but shouldn't the type cast operator be merged with the prefix unary group, instead of being in a group by itself? I can compile this without error with gcc 4.1.0:
int main()
{
        double foo = 1.0;

        ~(int)foo;

        return 0;
}
If the type cast operator has lower precedence than the bitwise one's complement operator, then the later should be evaluated first, and the compiler would produce the error "wrong type argument to bit-complement."

On the other hand, since these are both prefix operators and right-to-left associative, and if they both have the same precedence level, then the type cast will be evaluated first and there will be no error.

Grokking convoluted expressions

Posted Mar 20, 2007 1:41 UTC (Tue) by ldo (subscriber, #40946) [Link]

If the type cast operator has lower precedence than the bitwise one's complement operator, then the later should be evaluated first, and the compiler would produce the error "wrong type argument to bit-complement."

Well, actually no, since the syntax of your example is that bitwise-complement is applied to the result of the cast, there's no way not to do the cast first. (The only other way to try to interpret it is that bitwise-complement applies to the type, but C syntax doesn't allow that interpretation.)

You're right that it doesn't have any effect to separate cast out into its own grouping. However, I'm following the groupings in section A7 of K&R2, which puts casting into its own subsection, coming after the other prefix unary operators.

Grokking convoluted expressions

Posted Mar 20, 2007 14:41 UTC (Tue) by tjc (subscriber, #137) [Link]

Well, actually no, since the syntax of your example is that bitwise-complement is applied to the result of the cast, there's no way not to do the cast first.
Exactly, which is why the type cast operator can't *really* be at a level below the unary prefix operators. If it was, then the one's complement would be evaluated first, which would produce an error since the operand is a floating-point number.
I'm following the groupings in section A7 of K?R2, which puts casting into its own subsection, coming after the other prefix unary operators.
Thanks for the tip, I'll take a look at K?R2 when I get home. There's also a grammar at the back of the book that might reveal why they put the type cast operator in a separate group.

Grokking convoluted expressions

Posted Mar 24, 2007 15:06 UTC (Sat) by muwlgr (guest, #35359) [Link]

By incidence, I used to have a very similar page scotched to the wardrobe near my desk (printed from TurboC 2.0 help system). Very useful during learning C :>

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds