Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Operators and NPCness

23 views
Skip to first unread message

Shao Miller

unread,
Mar 15, 2013, 11:43:16 AM3/15/13
to
Three quick questions (relative to N1570):

1. Are () an operator in the context of primary-expression: ( expression ) ?

I'd answer "not really," but 6.5p1 seems to partition an expression into
operators, operands, object/function designator, side-effect-causer, or
combination. Then again, 42, on its own, wouldn't fit nicely into
these, either.

2. Is _Generic an operator?

I'd answer "not really," but same "concern" as above.

3. Do the () of #1 maintain unmentioned properties of the contained
expression for the resulting primary-expression, such as "null pointer
constant"?

I'd answer "yes," but I'm not sure why, since it's not exactly covered
by 6.5.1p5.

These questions prompted by a discussion (in another C-devoted forum) about:

(void *) (void *) 0 /* Not an NPC */
&*(void *) 0 /* Not an NPC */
(((((void *) 0)))) /* NPC */

--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily," -- Richard Harter

Bart van Ingen Schenau

unread,
Mar 17, 2013, 2:32:18 PM3/17/13
to
On Fri, 15 Mar 2013 11:43:16 -0400, Shao Miller wrote:

> Three quick questions (relative to N1570):
>
> 1. Are () an operator in the context of primary-expression: ( expression
> ) ?
>
> I'd answer "not really," but 6.5p1 seems to partition an expression into
> operators, operands, object/function designator, side-effect-causer, or
> combination. Then again, 42, on its own, wouldn't fit nicely into
> these, either.

No, they are punctuators, but not an operator because they don't have any
effect other than directing the parsing of the text.

>
> 2. Is _Generic an operator?
>
> I'd answer "not really," but same "concern" as above.

It is not referred to in the standard as being an operator, but if I
would have to describe it, I would describe it as one.

>
> 3. Do the () of #1 maintain unmentioned properties of the contained
> expression for the resulting primary-expression, such as "null pointer
> constant"?

Yes. A parenthesized expression can be part of an integer constant
expression as long as the other requirements are also met.
A null pointer constant is defined as being an integer constant
expression with the value 0 (or such cast to the type void*) and the
added parentheses do not affect the constant expression part of that.

>
> I'd answer "yes," but I'm not sure why, since it's not exactly covered
> by 6.5.1p5.

It is covered by combining 6.3.2.3p3 and 6.6.

>
> These questions prompted by a discussion (in another C-devoted forum)
> about:
>
> (void *) (void *) 0 /* Not an NPC */
> &*(void *) 0 /* Not an NPC */
> (((((void *) 0)))) /* NPC */

That last one is tricky and can probably be argued both ways.
I would consider a compiler that doesn't treat it as an NPC as being
particularly prickly, and it would be lowering that compilers QoI for me.

>
> --
> - Shao Miller

Bart v Ingen Schenau

Nick Bowler

unread,
Mar 22, 2013, 11:10:43 AM3/22/13
to
On Sun, 17 Mar 2013 18:32:18 +0000, Bart van Ingen Schenau wrote:
> On Fri, 15 Mar 2013 11:43:16 -0400, Shao Miller wrote:
[...]
>> These questions prompted by a discussion (in another C-devoted forum)
>> about:
>>
>> (void *) (void *) 0 /* Not an NPC */
>> &*(void *) 0 /* Not an NPC */
>> (((((void *) 0)))) /* NPC */
>
> That last one is tricky and can probably be argued both ways.
> I would consider a compiler that doesn't treat it as an NPC as being
> particularly prickly, and it would be lowering that compilers QoI for me.

I don't think it's simply a QoI issue, because the behaviour of the ?:
operator is different if one of its operands is a null pointer constant
(as opposed to "ordinary" null pointers). Consider the following:

#include <stdio.h>

int main(void)
{
_Generic(0? NULL: (int *)0, int *: puts("hello"), default: 0);
}

This prints hello, because the middle operand of ?: is a null pointer
constant, so the type of the controlling expression is int *. However,
if we replace NULL with an "ordinary" null pointer, e.g.,

_Generic(0? (void *)(void *)0: /* ... */)

then the program does *not* print hello. Neither the middle nor last
operand of ?: is a null pointer constant, so the type of the controlling
expression is void *. So by writing

_Generic(0? ((void *)0): /* ... */)

we now have a program whose actual output depends on whether the
expression ((void *)0) is a null pointer constant or not. If you think
about it, it really should be: it would be silly if implementations
could not provide a definition of NULL as

#define NULL ((void *)0)

as dropping the parentheses would run afoul of 7.1.2p5.

Cheers,
Nick
0 new messages