-6

In its own definition, a postfix operator is an operator specified after all of its operands.

In C11 Standard, a postfix operator is defined as:

6.5.2 Postfix operators

Syntax

postfix-expression:

    primary-expression
    postfix-expression [ expression ]
    postfix-expression ( argument-expression-listopt )
    postfix-expression . identifier
    postfix-expression -> identifier
    postfix-expression ++
    postfix-expression --
    ( type-name ) { initializer-list }
    ( type-name ) { initializer-list , }
  1. The standard calls the two parts before and after . and -> as operands, which I highlighted in bold in the following quote. Does it mean . and -> are actually infix operators, in spite of being called postfix operators in the standard?

    6.5.2.3 Structure and union members

    Constraints

    1 The first operand of the . operator shall have an atomic, qualified, or unqualified structure or union type, and the second operand shall name a member of that type.

    2 The first operand of the -> operator shall have type ‘‘pointer to atomic, qualified, or unqualified structure’’ or ‘‘pointer to atomic, qualified, or unqualified union’’, and the second operand shall name a member of the type pointed to.

  2. The subsections for [], () and compound literals don't mention the word "operands". So

    • are [] and () both unary postfix operators, with a (function) pointer name before them as their only operand, and what inside [] and () are not operands? This is what the accpeted reply says In a function call, what is the operator, and what are the operands?
    • What is the operator of compound literals, (), (type-name) or something else? initializer-list within {} might be not operand(s), just like the array index in [] and function arguments in (). {} might be not part of the operator, because it is used for enclosing the initializers. If the operator of compound literals is (type-name), does the compound literal operator not take any operand?
  3. Although cast operators are not postfix operators in C, it looks confusingly almost the same as compound literal operators.

    6.5.4 Cast operators Syntax

    cast-expression:
    
        unary-expression
        ( type-name ) cast-expression
    

    Constraints 2 Unless the type name specifies a void type, the type name shall specify atomic, qualified, or unqualified scalar type, and the operand shall have scalar type.

    So is a cast operator () or (type-name)? Is its operand cast-expression, or both type-name and cast-expression?

Thanks.

Tim
  • 1
  • 141
  • 372
  • 590
  • 2
    I **think** the C standard doesn't even specify a *postfix operator*, only a *postfix expression*. –  Aug 16 '17 at 13:22
  • Does "postfix expression" have meaning outside C? – Tim Aug 16 '17 at 13:27
  • 2
    language-lawyer questions can be interesting. But your latest ones seem to be in the form of "Is an expression an expression"? – bolov Aug 16 '17 at 13:43
  • @bolov "Is an expression an expression" I never asked anything like that. I don't think you understand my previous questions. – Tim Aug 16 '17 at 13:49
  • @FelixPalmen It mentions _postfix operator_ in the title of the section, and writes about things like `[]` being a "subscript operator". However, it does not mention "infix operator" anywhere in the standard, so I think OP's first question is moot. – Ian Abbott Aug 16 '17 at 13:52
  • @Tim don't take it so literally. In my opinion your questions deal with trivial or uninteresting standard wording. And by uninteresting I mean this: getting an answer for it won't change the way we program. What do I care if the standard calls `.` and `->` infix operators, postfix operators, simply operators or anything else. It won't change the way I understand how they work, it won't change the way we use them in code, it won't change the way I explain them to students. – bolov Aug 16 '17 at 13:56
  • @IanAbbott My question is whether the standard follows the definition of postfix in general. Infix is a general concept outside of C, so is postfix. There is nothing moot in my questions. – Tim Aug 16 '17 at 13:59
  • 1
    https://www.youtube.com/watch?v=FFEoX2LFrVU – bolov Aug 16 '17 at 14:02
  • @FelixPalmen The C Standard does define `postfix operators`. – alinsoar Aug 16 '17 at 14:02
  • @Tim My guess is that the standard writers decided to keep the "Postfix operators" title for historical reasons after compound literals were added to the standard. – Ian Abbott Aug 16 '17 at 14:03
  • @Ian: Thanks. 1) What are the operands and operators of compound literal then? 2) Note that `->` and `.` have been there, unlike compound literals. That is another confusion. – Tim Aug 16 '17 at 14:07
  • 1
    The standard doesn't mention "compound literal operator" anywhere, so I'd be disinclined to call it an operator, even though it is in the "Postfix operators" section. Rather, the "compound literal" is just a "postfix expression". – Ian Abbott Aug 16 '17 at 14:09
  • @Ian So do you mean that it is possible that compound literals don't have operators? – Tim Aug 16 '17 at 14:10
  • @Tim "_So do you mean that it is possible that compound literals don't have operators?_" IMHO, yes. They could have called the section "_Postfix operators and compound literals_", but that's a bit long-winded. – Ian Abbott Aug 16 '17 at 14:15
  • @Tim, I take your point about `.` and `->` being more like infix operators, but I tend to think of infix operators as operating on two _values_ or _objects_. Besides, they have to call the section something, and "_Postfix operators, structure and union member operators, and compound literals_" doesn't have a nice ring to it. What would _you_ call the section? – Ian Abbott Aug 16 '17 at 14:22
  • @IanAbbott I would need to understand the intention of the authors for grouping those operators under a section, to guess what name would be better. Note that in general, postfix can take any finite number of operands, instead of just one, and is just listed after all its operands. – Tim Aug 16 '17 at 14:26
  • @Tim: "Postfix" is a good *enough* name for how these operators behave with respect to their operands. They're all postfix-*ish*, at least. Practicality wins out over pedantry. – John Bode Aug 16 '17 at 14:31
  • @JohnBode I focus more on what the operator and operands are for each of the "postfix expressions", than renaming the "postfix expression" section. So what do you think of what the operators and operands are for the "postfix expressions" in my post? – Tim Aug 16 '17 at 14:34
  • 1
    @Tim: What the language definition says they are. The operands of the `[]` operator are the array expression and the index. The operands of the `()` operator are the function expression and parameter expressions. The operands of the `.` and `->` operators are the `struct` (or `struct` pointer) expressions and the member name. They're lumped together with the postfix `++` and `--` operators to make sure they all have the same precedence. – John Bode Aug 16 '17 at 14:45
  • @JohnBode Thanks. 1) What about compound literals? Do you think there is no operator or operand? 2) `()` and `[]` are unary operators, as mentioned in the accepted reply here https://stackoverflow.com/questions/45615818/in-a-function-call-what-is-the-operator-and-what-are-the-operands – Tim Aug 16 '17 at 14:48
  • @Tim The intention of the grouping is to define the hierarchy of the different forms of expression; basically, operator precedence. – Ian Abbott Aug 16 '17 at 14:58
  • @Tim you could compare this with [the Python grammar](https://docs.python.org/3/reference/grammar.html) - many of the symbol names there are *completely ridiculous* (`test_nocond`, `testlist_comp`, `lambdef_nocond`)- but one just needs to invent *some* name for these non-terminals. – Antti Haapala -- Слава Україні Aug 17 '17 at 21:31

2 Answers2

5
  1. The language specification defines the syntax, and doesn't care what you call the parts that make up the language.

    In abc->def, the first operand is abc, and -> is the operator and def is the second operand, but it is restricted to an identifier is the name of a member of the structure or union of the type that the first operand (which may be a full-blown postfix-expression) identifies. You can't write general expressions on the RHS of the -> operator — abc->3 doesn't work, and neither does abc->(x + y). Similar comments apply to the . operator, mutatis mutandis.

    If you want to think of this as an infix operator, you may do so. That's your privilege. It won't help you understand the standard.

  2. (a) The [] operator follows a postfix expression; it is after the postfix expression; that makes it a postfix operator.
    (b) The () function-call operator follows a postfix expression; it is after a postfix expression; that makes it a postfix operator.
    (c) The compound literal operator is all of (type){ and }. Since the { … } comes after the (type) part, and since it behaves like other postfix operators in the syntax, it is reasonable to regard it as a postfix operator. The standard says it is one; it really doesn't matter anyway. The language works as specified.

  3. The cast operators are separately grouped, and a kind of 'prefix operator'. They are distinct from compound literals. The expression after a cast cannot start with an {; the literal after the 'cast notation' in a compound literal can only start with a {. The presence or absence of { is determinative of whether the construct is a cast or a compound literal.

All of this is pretty obvious if you read and understand the standard.


  1. (a) and (b) The C standard doesn't say that "it is after the postfix expression; that makes it a postfix operator." I am not sure what that mean either. In general outside C, an operator is called postfix, if it appears after all its operands.

The standard says that one of the ways of building a postfix-expression is:

postfix-expression [ expression ]

From where I'm sitting, "The [] operator follows a postfix expression; it is after the postfix expression; that makes it a postfix operator" seems a reasonably accurate description of that portion of the syntax. The [ and ] appear after a prior postfix-expression. I'm not sure what else you'd understand by a 'postfix operator' than 'an operator that comes after something', and the [] comes after 'something'.

2(c) my intuition from reading the books on C so far suggests that initialization parts are not operands or operators, so I doubt that {} is part of the operator of compound literal.

A compound literal consists of a type name enclosed in round brackets (parentheses) followed by an initializer list enclosed in curly brackets (braces). It takes all of that to make a compound literal. I don't see how the {} could not be a part of the compound literal — the syntax says it is, and … well, if you want to think of it as something separate, I can't stop you, but you're making your own life more difficult by doing so and making life very difficult for those people on SO trying to help you. It really isn't clear from this side of my screen how you manage to come up with these new ways to misinterpret the plain text of the standard so cleverly and deviously.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Thanks. I upvoted, though the standard doesn't address the confusions that I have. So it is unlike that "All of this is pretty obvious if you read and understand the standard." I updated my post to explain more. 1. Instead of me "call the parts that make up the language", it was the standard which calls the parts after `.`. and `->` as the second operands. – Tim Aug 16 '17 at 15:46
  • 2. (a) and (b) The C standard doesn't say that "it is after the postfix expression; that makes it a postfix operator." I am not sure what that mean either. In general outside C, an operator is called postfix, if it appears after all its operands. 2(c) my intuition from reading the books on C so far suggests that initialization parts are not operands or operators, so I doubt that `{}` is part of the operator of compound literal. – Tim Aug 16 '17 at 15:46
  • I doubted. But your reply about it makes more sense. So I tended to think of `{}` as part of compound literal operator. – Tim Aug 16 '17 at 16:01
  • The Standard says that an operator is a punctuator that specifies an operation to be performed, and that ["other forms of operator also exist in some contexts"](http://port70.net/~nsz/c/c11/n1570.html#6.4.6p2). Maybe the notation for compound literals should be thought of as belonging to this class. – ad absurdum Aug 16 '17 at 16:14
2

Edit

I'm operating on a bit of a sleep deficit, combined with a little too much coffee, so my mental processes aren't operating as clearly as they could, hence the confused sludge in my original response.

These operators are called "postfix operators" because they follow a postfix-expression, not because of the number or position of their operands. Similarly, prefix operators are called "unary operators" because they precede a unary-expression. "Cast operators" precede a cast-expression, "multiplicative operators" follow multiplicative-expressions, etc. IOW, the operators are named for the types of expressions they apply to, not because of the operator's intrinsic properties.

Original

You're overthinking things to an extent.

The primary reason (), [], ., ->, and compound literals are grouped with postfix ++ and -- is to make sure they all have the same (highest level of) precedence; that expressions like &a[i], *f(x), and a + b->c are all parsed as &(a[i]), *(f(x)), and a + (b->c). The choice of the term "postfix" to describe these operators is unfortunate if you insist on being pedantic about its meaning1, but it kinda-sorta makes sense in context. The main reason they're called "postfix operators" is that they follow a postfix-expression, not because of the number or position of operands.

The language standard is mostly well-written and precise, but there are some areas where it could be better. This may be one of those areas.


  1. Note that the standard uses "unary" as opposed to "prefix" to describe the leading *, &, ++, --, and sizeof operators, even though they hew far more closely to the idea of a prefix operator than the postfix operators do. Again, it's because these operators precede a unary-expression, not because of the number or position of operands.

John Bode
  • 119,563
  • 19
  • 122
  • 198