Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #112475 > unrolled thread

Null pointer constant

Started bybartc <bc@freeuk.com>
First post2017-06-18 17:15 +0100
Last post2017-06-19 12:34 -0700
Articles 20 on this page of 111 — 14 participants

Back to article view | Back to comp.lang.c


Contents

  Null pointer constant bartc <bc@freeuk.com> - 2017-06-18 17:15 +0100
    Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-18 11:20 -0700
    Re: Null pointer constant Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-06-18 19:23 +0100
      Re: Null pointer constant bartc <bc@freeuk.com> - 2017-06-18 20:57 +0100
        Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-18 13:38 -0700
          Re: Null pointer constant Tim Rentsch <txr@alumni.caltech.edu> - 2017-06-19 04:35 -0700
            Re: Null pointer constant Nick Bowler <nbowler@draconx.ca> - 2017-06-19 18:08 +0000
              Re: Null pointer constant Tim Rentsch <txr@alumni.caltech.edu> - 2017-06-19 21:05 -0700
            Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-19 12:12 -0700
              Re: Null pointer constant Tim Rentsch <txr@alumni.caltech.edu> - 2017-06-19 21:08 -0700
        Re: Null pointer constant Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-06-19 00:34 +0100
          Re: Null pointer constant Tim Rentsch <txr@alumni.caltech.edu> - 2017-06-19 04:45 -0700
            Re: Null pointer constant David Brown <david.brown@hesbynett.no> - 2017-06-19 13:55 +0200
          Re: Null pointer constant bartc <bc@freeuk.com> - 2017-06-19 13:16 +0100
            Re: Null pointer constant Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-06-19 16:58 +0100
    Re: Null pointer constant Ike Naar <ike@iceland.freeshell.org> - 2017-06-18 20:58 +0000
      Re: Null pointer constant bartc <bc@freeuk.com> - 2017-06-19 00:11 +0100
        Re: Null pointer constant David Brown <david.brown@hesbynett.no> - 2017-06-19 03:21 +0200
          Re: Null pointer constant bartc <bc@freeuk.com> - 2017-06-19 10:11 +0100
            Re: Null pointer constant David Brown <david.brown@hesbynett.no> - 2017-06-19 12:38 +0200
              Re: Null pointer constant bartc <bc@freeuk.com> - 2017-06-19 13:05 +0100
                Re: Null pointer constant David Brown <david.brown@hesbynett.no> - 2017-06-19 14:39 +0200
                  Re: Null pointer constant "James R. Kuyper" <jameskuyper@verizon.net> - 2017-06-19 11:06 -0400
                    Re: Null pointer constant Ike Naar <ike@iceland.freeshell.org> - 2017-06-19 15:51 +0000
                      Re: Null pointer constant "James R. Kuyper" <jameskuyper@verizon.net> - 2017-06-19 12:22 -0400
                        Re: Null pointer constant Ike Naar <ike@iceland.freeshell.org> - 2017-06-19 17:29 +0000
                          Re: Null pointer constant "James R. Kuyper" <jameskuyper@verizon.net> - 2017-06-19 13:45 -0400
                            Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-19 12:31 -0700
                  Re: Null pointer constant Ike Naar <ike@iceland.freeshell.org> - 2017-06-19 15:10 +0000
                  Re: Null pointer constant Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-06-19 16:53 +0100
                    Re: Null pointer constant "James R. Kuyper" <jameskuyper@verizon.net> - 2017-06-19 13:06 -0400
                      Re: Null pointer constant Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-06-19 20:03 +0100
                    Re: Null pointer constant David Brown <david.brown@hesbynett.no> - 2017-06-19 22:37 +0200
                      Re: Null pointer constant Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-06-19 22:10 +0100
                        Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-19 14:25 -0700
                          Re: Null pointer constant Tim Rentsch <txr@alumni.caltech.edu> - 2017-06-19 22:46 -0700
                            Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-20 08:43 -0700
                              Re: Null pointer constant supercat@casperkitty.com - 2017-06-20 09:17 -0700
                              Re: Null pointer constant Tim Rentsch <txr@alumni.caltech.edu> - 2017-06-21 00:56 -0700
                                Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-21 10:07 -0700
                                  Re: Null pointer constant Tim Rentsch <txr@alumni.caltech.edu> - 2017-06-21 23:52 -0700
                                    Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-22 10:12 -0700
                                      Re: Null pointer constant Tim Rentsch <txr@alumni.caltech.edu> - 2017-06-22 17:33 -0700
                                        Re: Null pointer constant supercat@casperkitty.com - 2017-06-23 08:54 -0700
                    Re: Null pointer constant Manfred <invalid@invalid.add> - 2017-06-20 00:00 +0200
                      Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-19 15:27 -0700
                        Re: Null pointer constant supercat@casperkitty.com - 2017-06-19 16:38 -0700
                        Re: Null pointer constant Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-06-20 01:14 +0100
                          Re: Null pointer constant Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-06-20 12:03 +0100
                        Re: Null pointer constant Manfred <noname@invalid.add> - 2017-06-20 13:16 +0200
                          Re: Null pointer constant jameskuyper@verizon.net - 2017-06-20 05:34 -0700
                          Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-20 08:49 -0700
                        Re: Null pointer constant Ike Naar <ike@iceland.freeshell.org> - 2017-06-20 16:35 +0000
                          Re: Null pointer constant "James R. Kuyper" <jameskuyper@verizon.net> - 2017-06-20 13:07 -0400
                            Re: Null pointer constant Nick Bowler <nbowler@draconx.ca> - 2017-06-20 17:29 +0000
                              Re: Null pointer constant "James R. Kuyper" <jameskuyper@verizon.net> - 2017-06-20 13:55 -0400
                                Re: Null pointer constant Nick Bowler <nbowler@draconx.ca> - 2017-06-20 18:06 +0000
                                  Re: Null pointer constant "James R. Kuyper" <jameskuyper@verizon.net> - 2017-06-20 14:42 -0400
                                    Re: Null pointer constant Nick Bowler <nbowler@draconx.ca> - 2017-06-20 19:10 +0000
                            Re: Null pointer constant Ike Naar <ike@iceland.freeshell.org> - 2017-06-20 18:31 +0000
                              Re: Null pointer constant Nick Bowler <nbowler@draconx.ca> - 2017-06-20 18:36 +0000
                              Re: Null pointer constant "James R. Kuyper" <jameskuyper@verizon.net> - 2017-06-20 14:45 -0400
                          Re: Null pointer constant Nick Bowler <nbowler@draconx.ca> - 2017-06-20 17:14 +0000
                          Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-20 11:55 -0700
                            Re: Null pointer constant Nick Bowler <nbowler@draconx.ca> - 2017-06-20 19:23 +0000
                              Re: Null pointer constant "James R. Kuyper" <jameskuyper@verizon.net> - 2017-06-20 15:39 -0400
                                Re: Null pointer constant scott@slp53.sl.home (Scott Lurndal) - 2017-06-21 13:44 +0000
                                  Re: Null pointer constant scott@slp53.sl.home (Scott Lurndal) - 2017-06-21 13:49 +0000
                                Re: Null pointer constant Tim Rentsch <txr@alumni.caltech.edu> - 2017-06-21 23:57 -0700
                                  Re: Null pointer constant Philip Lantz <prl@canterey.us> - 2017-06-28 20:04 -0700
                                  Re: Null pointer constant Tim Rentsch <txr@alumni.caltech.edu> - 2017-07-10 08:38 -0700
                              Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-20 12:39 -0700
                                Re: Null pointer constant bartc <bc@freeuk.com> - 2017-06-20 20:53 +0100
                                  Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-20 13:07 -0700
                                Re: Null pointer constant Nick Bowler <nbowler@draconx.ca> - 2017-06-20 20:50 +0000
                                  Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-20 15:35 -0700
                          Re: Null pointer constant Tim Rentsch <txr@alumni.caltech.edu> - 2017-06-21 00:26 -0700
                            Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-21 09:54 -0700
                              Re: Null pointer constant "James R. Kuyper" <jameskuyper@verizon.net> - 2017-06-21 13:09 -0400
                                Re: Null pointer constant Tim Rentsch <txr@alumni.caltech.edu> - 2017-06-22 00:53 -0700
                              Re: Null pointer constant bartc <bc@freeuk.com> - 2017-06-21 18:09 +0100
                              Re: Null pointer constant Tim Rentsch <txr@alumni.caltech.edu> - 2017-06-22 00:50 -0700
                  Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-19 10:24 -0700
                    Re: Null pointer constant Tim Rentsch <txr@alumni.caltech.edu> - 2017-06-19 22:32 -0700
                  Re: Null pointer constant bartc <bc@freeuk.com> - 2017-06-19 19:40 +0100
                  Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-19 12:08 -0700
                    Re: Null pointer constant bartc <bc@freeuk.com> - 2017-06-19 20:32 +0100
                      Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-19 12:48 -0700
                      Re: Null pointer constant jameskuyper@verizon.net - 2017-06-19 13:08 -0700
                        Re: Null pointer constant Nick Bowler <nbowler@draconx.ca> - 2017-06-19 20:40 +0000
                        Re: Null pointer constant bartc <bc@freeuk.com> - 2017-06-19 22:01 +0100
                          Re: Null pointer constant supercat@casperkitty.com - 2017-06-19 14:15 -0700
                          Re: Null pointer constant jameskuyper@verizon.net - 2017-06-19 14:25 -0700
                    Re: Null pointer constant Ike Naar <ike@iceland.freeshell.org> - 2017-06-19 21:06 +0000
                      Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-19 14:28 -0700
                        Re: Null pointer constant Ike Naar <ike@iceland.freeshell.org> - 2017-06-19 21:35 +0000
                          Re: Null pointer constant supercat@casperkitty.com - 2017-06-19 14:48 -0700
                            Re: Null pointer constant Ike Naar <ike@iceland.freeshell.org> - 2017-06-20 15:38 +0000
                          Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-19 15:16 -0700
                    Re: Null pointer constant supercat@casperkitty.com - 2017-06-19 14:29 -0700
                      Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-19 15:18 -0700
                        Re: Null pointer constant Tim Rentsch <txr@alumni.caltech.edu> - 2017-06-19 22:48 -0700
                  Re: Null pointer constant bartc <bc@freeuk.com> - 2017-06-20 15:09 +0100
                Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-19 10:19 -0700
              Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-19 10:15 -0700
                Re: Null pointer constant David Brown <david.brown@hesbynett.no> - 2017-06-19 22:44 +0200
              Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-19 12:24 -0700
        Re: Null pointer constant Ike Naar <ike@iceland.freeshell.org> - 2017-06-19 08:21 +0000
          Re: Null pointer constant bartc <bc@freeuk.com> - 2017-06-19 10:17 +0100
            Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-19 10:04 -0700
    Re: Null pointer constant Keith Thompson <kst-u@mib.org> - 2017-06-19 12:34 -0700

Page 3 of 6 — ← Prev page 1 2 [3] 4 5 6  Next page →


#112820

FromTim Rentsch <txr@alumni.caltech.edu>
Date2017-06-21 23:52 -0700
Message-ID<kfntw385xa7.fsf@x-alumni2.alumni.caltech.edu>
In reply to#112808
Keith Thompson <kst-u@mib.org> writes:

> Tim Rentsch <txr@alumni.caltech.edu> writes:
>
>> Keith Thompson <kst-u@mib.org> writes:
>
> [...]
>
>>> One could argue that the intent is that an implementation may
>>> accept other forms of constant expression *without a diagnostic*.
>>
>> I agree;  one could so argue.  I think it would be hard to
>> make the argument convincing, but certainly one could be made.
>>
>>> If not, 6.6p10 "An implementation may accept other forms of
>>> constant expressions." would seem to be redundant, since it's
>>> already covered by the permission to provide extensions.
>>
>> I don't think 6.6 p10 is redundant, because only some of the
>> restrictions on various forms of constant expressions are
>> constraints.  In 6.6 p6, for example, there are restrictions
>> on integer constant expressions that are not constraints.
>> The allowance in 6.6 p10 could be used to establish other
>> forms of integer constant expressions but which still did
>> not violate the constraints in 6.6 p3.
>
> Hmm.  Straying a bit into more quibbling, 6.6p6, defining "integer
> constant expression", uses the word "shall" repeatedly:
>
>     An *integer constant expression* shall have integer type and shall
>     only have operands that are integer constants, ...
>
> The standard defines what it means by "shall" (4p1-2), and since
> 6.6p6 is not a constraint it implies that violating it causes
> undefined behavior.  Which would mean that `case 0.0:` does not
> require a diagnostic, but does have undefined behavior.

That isn't how I read it.  There are two kinds of "shall"s,
either a requirement on an implementation or a requirement on a
program.  The "shall"s in 6.6 p6 are clearly meant to be for
implementations, not programs.  Not meeting an implementation
requirement means the implementation is not conforming, and the
Standard doesn't have anything to say about non-conforming
implementations except that they are not conforming.

> I don't think that was the intent.  Rather I think the intent is
> that 0.0 *is not* an integer constant expression, and using it
> in a case label violates the constraint that the expression shall
> be an integer constant expression (6.8.4.2p3).

Yes, I believe that follows when 6.6 p6 is read as imposing a set
of requirements on implementations rather than being requirements
on programs.

> I suggest that the
> restrictions in 6.6p6 should be considered part of the definition of
> "integer constant expression", and should not be stated using the
> word "shall".

I think "shall" is actually appropriate here, but it would be
nice if the text were more clear that it is implementations
that are the target of the requirement, and not programs.

By the way, note a key difference between 6.6 p10 and extensions.
Any extension must be documented, but AFAIK any new forms of
various kinds of constant expressions accepted under 6.6 p10 do
/not/ have to be documented.  (There is also the difference that a
new form of constant expression /as an extension/ would probably
require some sort of diagnostic, which 6.6 p10 can circumvent in
many cases.)

[toc] | [prev] | [next] | [standalone]


#112839

FromKeith Thompson <kst-u@mib.org>
Date2017-06-22 10:12 -0700
Message-ID<lnr2ycaqux.fsf@kst-u.example.com>
In reply to#112820
Tim Rentsch <txr@alumni.caltech.edu> writes:
> Keith Thompson <kst-u@mib.org> writes:
>> Tim Rentsch <txr@alumni.caltech.edu> writes:
>>
>>> Keith Thompson <kst-u@mib.org> writes:
>>
>> [...]
>>
>>>> One could argue that the intent is that an implementation may
>>>> accept other forms of constant expression *without a diagnostic*.
>>>
>>> I agree;  one could so argue.  I think it would be hard to
>>> make the argument convincing, but certainly one could be made.
>>>
>>>> If not, 6.6p10 "An implementation may accept other forms of
>>>> constant expressions." would seem to be redundant, since it's
>>>> already covered by the permission to provide extensions.
>>>
>>> I don't think 6.6 p10 is redundant, because only some of the
>>> restrictions on various forms of constant expressions are
>>> constraints.  In 6.6 p6, for example, there are restrictions
>>> on integer constant expressions that are not constraints.
>>> The allowance in 6.6 p10 could be used to establish other
>>> forms of integer constant expressions but which still did
>>> not violate the constraints in 6.6 p3.
>>
>> Hmm.  Straying a bit into more quibbling, 6.6p6, defining "integer
>> constant expression", uses the word "shall" repeatedly:
>>
>>     An *integer constant expression* shall have integer type and shall
>>     only have operands that are integer constants, ...
>>
>> The standard defines what it means by "shall" (4p1-2), and since
>> 6.6p6 is not a constraint it implies that violating it causes
>> undefined behavior.  Which would mean that `case 0.0:` does not
>> require a diagnostic, but does have undefined behavior.
>
> That isn't how I read it.  There are two kinds of "shall"s,
> either a requirement on an implementation or a requirement on a
> program.  The "shall"s in 6.6 p6 are clearly meant to be for
> implementations, not programs.  Not meeting an implementation
> requirement means the implementation is not conforming, and the
> Standard doesn't have anything to say about non-conforming
> implementations except that they are not conforming.

Hmm.  I don't see it.

First, I'll take a closer look at 4p1-2:

    1. In this International Standard, "shall" is to be interpreted as a
    requirement on an implementation or on a program; conversely, "shall
    not" is to be interpreted as a prohibition.

    2 If a "shall" or "shall not" requirement that appears outside of a
    constraint or runtime-constraint is violated, the behavior is
    undefined.

Would you agree that that last statement applies only to shalls
and shall nots that are requirements on programs?  (I wouldn't mind
that being stated explicitly.)  A requirement on an implementation
is one that an implementation must satisfy to be conforming.  If an
implementation is not conforming, the standard has nothing further
to say about it.

A "shall" can apply either to an implementation or to a program.

6.6p5: "If a floating expression is evaluated in the translation
environment, the arithmetic range and precision shall be at
least as great as if the expression were being evaluated in the
execution environment."  That's pretty clearly a requirement on
the implementation.

6.6p6: "An *integer constant expression* shall have integer type
and shall only have operands that are integer constants, [snip]".
That's the definition of "integer constant expression"; it tells
us what is an ICE and what is not an ICE.  If it's a requirement
on the implementation, it's not clear what it requires.  There are
already requirements elsewhere for the implementation to diagnose
a failure to use an ICE where one is required (actually stated as
a requirement on programs).

Most other definitions of terms don't use "shall" this way.
Why should this one?  I think it would be clearer if written as:
"An *integer constant expression* is a constant expression that has
integer type and only has operands that are integer constants, ...".

Annex J is informative, not normative.  J.2p1 lists instances of
undefined behavior.  One of the cases is:

    An expression that is required to be an integer constant
    expression does not have an integer type; has operands that
    are not integer constants, [snip]

It makes no sense to me that, for example, a case label:
    case "foo":
has undefined behavior rather than being an error that must be
diagnosed.  It appears that whoever wrote annex J assumed that the
"shalls" in 6.6 are requirements on a program.  (I'm assuming that
violation of a requirement on an implementation doesn't result in
undefined behavior.)  I wonder whether 6.6 and J were written by
different people.

[...]

> By the way, note a key difference between 6.6 p10 and extensions.
> Any extension must be documented, but AFAIK any new forms of
> various kinds of constant expressions accepted under 6.6 p10 do
> /not/ have to be documented.

Which seems odd.  It would be silly for an implementation to
support other forms of constant expression and not document them.
I'd say this is an oversight; any additional forms should IMHO
be implementation-defined.

>                               (There is also the difference that a
> new form of constant expression /as an extension/ would probably
> require some sort of diagnostic, which 6.6 p10 can circumvent in
> many cases.)

How so?  I note that you recently cited DR #032,
http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_032.html, which
says that an implementation that accepts (1, 2) as a constant
expression must still diagnose it as a constraint violation.

I have a possibly related question (I'm not sure yet whether the answer
has any actual effect).  Can an expression that appears in a context
that doesn't require a constant expression be a constant expression?

For example, the definition of "null pointer constant" (which is not
mentioned in the grammar) is such that 0 is a null pointer constant
whether it appears in a pointer context or not.  Given
    int i = 0;
`i` is by definition an NPC, but the fact that it's an NPC is of
no relevance.  At least that's what I've always assumed.

On the other hand, given
    int i = 2 + 3*4;
`2 + 3` has the form of an additive-expression, but it isn't one,
nor is it an expression.

"constant-expression" is defined in the grammar, though most of the
definition is in the English wording in 6.6.  Given the assignment
    i = 42;
42 has the form of a constant-expression and meets the requirements,
but it doesn't parse as a constant-expression in the grammar.

As I started to write this, I was thinking that an expression isn't a
constant-expression unless it appears on a context that requires one --
but then in this declaration at block scope:
    int *p = 0;
since the context doesn't require a constant expression, 0 wouldn't
be a constant expression, therefore it wouldn't be an integer
constant expression, and therefore it wouldn't be a null pointer
constant.  Oops.

Resolving all this requires a lamentable application of common sense.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#112874

FromTim Rentsch <txr@alumni.caltech.edu>
Date2017-06-22 17:33 -0700
Message-ID<kfn4lv75yr6.fsf@x-alumni2.alumni.caltech.edu>
In reply to#112839
Keith Thompson <kst-u@mib.org> writes:

> Tim Rentsch <txr@alumni.caltech.edu> writes:
>
>> Keith Thompson <kst-u@mib.org> writes:
>>
>>> Tim Rentsch <txr@alumni.caltech.edu> writes:
>>>
>>>> Keith Thompson <kst-u@mib.org> writes:
>>>
>>> [...]
>>>
>>>>> One could argue that the intent is that an implementation may
>>>>> accept other forms of constant expression *without a diagnostic*.
>>>>
>>>> I agree;  one could so argue.  I think it would be hard to
>>>> make the argument convincing, but certainly one could be made.
>>>>
>>>>> If not, 6.6p10 "An implementation may accept other forms of
>>>>> constant expressions." would seem to be redundant, since it's
>>>>> already covered by the permission to provide extensions.
>>>>
>>>> I don't think 6.6 p10 is redundant, because only some of the
>>>> restrictions on various forms of constant expressions are
>>>> constraints.  In 6.6 p6, for example, there are restrictions
>>>> on integer constant expressions that are not constraints.
>>>> The allowance in 6.6 p10 could be used to establish other
>>>> forms of integer constant expressions but which still did
>>>> not violate the constraints in 6.6 p3.
>>>
>>> Hmm.  Straying a bit into more quibbling, 6.6p6, defining "integer
>>> constant expression", uses the word "shall" repeatedly:
>>>
>>>     An *integer constant expression* shall have integer type and shall
>>>     only have operands that are integer constants, ...
>>>
>>> The standard defines what it means by "shall" (4p1-2), and since
>>> 6.6p6 is not a constraint it implies that violating it causes
>>> undefined behavior.  Which would mean that `case 0.0:` does not
>>> require a diagnostic, but does have undefined behavior.
>>
>> That isn't how I read it.  There are two kinds of "shall"s,
>> either a requirement on an implementation or a requirement on a
>> program.  The "shall"s in 6.6 p6 are clearly meant to be for
>> implementations, not programs.  Not meeting an implementation
>> requirement means the implementation is not conforming, and the
>> Standard doesn't have anything to say about non-conforming
>> implementations except that they are not conforming.
>
> Hmm.  I don't see it.

Let me say at the outset that my responses below are not meant as
statements of fact but just as presenting my view or perception.
I'm not trying argue about what is true but simply explain how
I see things.  okay?

> First, I'll take a closer look at 4p1-2:
>
>     1. In this International Standard, "shall" is to be interpreted as a
>     requirement on an implementation or on a program;  conversely, "shall
>     not" is to be interpreted as a prohibition.
>
>     2 If a "shall" or "shall not" requirement that appears outside of a
>     constraint or runtime-constraint is violated, the behavior is
>     undefined.
>
> Would you agree that that last statement applies only to shalls
> and shall nots that are requirements on programs?

I don't know if it does, and I don't know if it matters whether
it does or not.

> (I wouldn't mind
> that being stated explicitly.)  A requirement on an implementation
> is one that an implementation must satisfy to be conforming.  If an
> implementation is not conforming, the standard has nothing further
> to say about it.

To me it seems consistent to say that an implementation violating
a "shall" requirement (that is meant to apply to implementations)
is undefined behavior, because such an implementation is not
conforming, and the Standard imposes no requirements on any
implementation that is not conforming, which is pretty much the
same as saying the behavior is undefined.

I agree that the reasoning there is rather circular, but I think
it is self-consistent.


> A "shall" can apply either to an implementation or to a program.
>
> 6.6p5:  "If a floating expression is evaluated in the translation
> environment, the arithmetic range and precision shall be at
> least as great as if the expression were being evaluated in the
> execution environment."  That's pretty clearly a requirement on
> the implementation.
>
> 6.6p6:  "An *integer constant expression* shall have integer type
> and shall only have operands that are integer constants, [snip]".
> That's the definition of "integer constant expression";  it tells
> us what is an ICE and what is not an ICE.  If it's a requirement
> on the implementation, it's not clear what it requires.  There are
> already requirements elsewhere for the implementation to diagnose
> a failure to use an ICE where one is required (actually stated as
> a requirement on programs).

I believe it requires an implementation to accept as an ICE any
expression that satisfies the stated conditions (and also can be
evaluated at translation time, etc).

> Most other definitions of terms don't use "shall" this way.
> Why should this one?  I think it would be clearer if written as:
> "An *integer constant expression* is a constant expression that has
> integer type and only has operands that are integer constants, ...".

I don't think of the "shall" elements as being definitional but
as stating conditions regarding what an imlementation must
accept.  The re-write you propose is IMO not appropriate because
the intent of the "shall"s is not to define the term but to put
a lower bound on what forms of expressions must be accepted as
ICE's.

Yes, this idea is seemingly at odds with the use of italics
around the phrase "integer constant expression" but it is my view
nonetheless.  There are (at least) several other places the
Standard does something similar:  give a term in italics, meaning
a definition, but the "definition" doesn't define the term but
instead gives some properties that the term has.  Personally that
drives me a little bit crazy, but I think you'll agree that it
occurs in various places.


> Annex J is informative, not normative.  J.2p1 lists instances of
> undefined behavior.  One of the cases is:
>
>     An expression that is required to be an integer constant
>     expression does not have an integer type;  has operands that
>     are not integer constants, [snip]
>
> It makes no sense to me that, for example, a case label:
>     case "foo":
> has undefined behavior rather than being an error that must be
> diagnosed.  It appears that whoever wrote annex J assumed that the
> "shalls" in 6.6 are requirements on a program.  (I'm assuming that
> violation of a requirement on an implementation doesn't result in
> undefined behavior.)  I wonder whether 6.6 and J were written by
> different people.

In practice I don't think it matters whether the "shall"s in
6.6p6 are viewed as implementation requirements or as program
requirements.  Implementations are going to give diagnostics for
any expression that needs to be an ICE that the implementation
doesn't consider an ICE, no matter what Annex J says.  To me it
seems more natural to consider these conditions as applying to
the implementation rather than to the program text, but in
practice I don't there is any difference.


>> By the way, note a key difference between 6.6 p10 and extensions.
>> Any extension must be documented, but AFAIK any new forms of
>> various kinds of constant expressions accepted under 6.6 p10 do
>> /not/ have to be documented.
>
> Which seems odd.  It would be silly for an implementation to
> support other forms of constant expression and not document them.
> I'd say this is an oversight;  any additional forms should IMHO
> be implementation-defined.

First, I don't think it was an oversight.  Second, I disagree.
Part of the motivation for 6.6 p10 is to allow other forms of,
eg, ICEs, that the implementation accepts for its own purposes,
not so programs can use them.  Requiring those to be documented
would be counter-productive.  (An example is the expansion of
the offsetof() macro.)

>>                               (There is also the difference that a
>> new form of constant expression /as an extension/ would probably
>> require some sort of diagnostic, which 6.6 p10 can circumvent in
>> many cases.)
>
> How so?  I note that you recently cited DR #032,
> http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_032.html, which
> says that an implementation that accepts (1, 2) as a constant
> expression must still diagnose it as a constraint violation.

Right, but I'm talking about syntactic forms that don't violate
the syntactic constraints but just need help with the semantic
restrictions, as for example

    int foo[ (int)( 1. / 0.1 ) ];

If the "shall"s in 6.6 p6 are seen as being part of the definition
of "integer constant expression", then something like 6.6 p10 is
needed to avoid having to give a diagnostic in cases like the one
shown above.


> I have a possibly related question (I'm not sure yet whether the answer
> has any actual effect).  Can an expression that appears in a context
> that doesn't require a constant expression be a constant expression?
>
> For example, the definition of "null pointer constant" (which is not
> mentioned in the grammar) is such that 0 is a null pointer constant
> whether it appears in a pointer context or not.  Given
>     int i = 0;
> `i` is by definition an NPC, but the fact that it's an NPC is of
> no relevance.  At least that's what I've always assumed.
>
> On the other hand, given
>     int i = 2 + 3*4;
> `2 + 3` has the form of an additive-expression, but it isn't one,
> nor is it an expression.

I assume any use of a syntactic non-terminal must correspond to an
appearance of that non-terminal in the parse tree of the program
as a whole.  Considered in isolation, the phrase '2+3' is an
additive-expression, but that correspondence does not appear in
the parse tree for the program as a whole.  Hence that
identification is not apropos for this program fragment.

> "constant-expression" is defined in the grammar, though most of the
> definition is in the English wording in 6.6.  Given the assignment
>     i = 42;
> 42 has the form of a constant-expression and meets the requirements,
> but it doesn't parse as a constant-expression in the grammar.

Right.  I believe the intention is that any expression that needs
to be a constant expression must syntactically reduce to a
constant-expression non-terminal.  In addition, there are a few
places where a constant-expression non-terminal is actually part
of the syntax, but that doesn't cover all the places where a
conditional expression is needed.  The reason is, in those other
places, the need for a constant expression is semantic rather
than syntactic.

> As I started to write this, I was thinking that an expression isn't a
> constant-expression unless it appears on a context that requires one --
> but then in this declaration at block scope:
>     int *p = 0;
> since the context doesn't require a constant expression, 0 wouldn't
> be a constant expression, therefore it wouldn't be an integer
> constant expression, and therefore it wouldn't be a null pointer
> constant.  Oops.
>
> Resolving all this requires a lamentable application of common sense.

I don't have that reaction.  To me it seems pretty clear:  if the
semantic circumstances need a constant expression, then the
expression in question must reduce to constant-expression.  Or,
looked at the other way, if the expression in question does not
reduce to constant-expression, then it cannot be used as a
constant expression, which forces either an alternate semantic
choice (eg, in the case of VLA's) or a constraint violation and
a mandatory diagnostic (eg, for a pointer initializer having an
integer type).

How much did my answers and/or responses help you?

[toc] | [prev] | [next] | [standalone]


#112905

Fromsupercat@casperkitty.com
Date2017-06-23 08:54 -0700
Message-ID<1a5bedbe-8481-45d4-9bc0-3a6ef690ca18@googlegroups.com>
In reply to#112874
On Thursday, June 22, 2017 at 7:33:26 PM UTC-5, Tim Rentsch wrote:
> To me it seems consistent to say that an implementation violating
> a "shall" requirement (that is meant to apply to implementations)
> is undefined behavior, because such an implementation is not
> conforming, and the Standard imposes no requirements on any
> implementation that is not conforming, which is pretty much the
> same as saying the behavior is undefined.

The most general way to describe "shall" requirements in standards is to say
that for an X to be an Y, it must uphold all "shall" requirements associated
with Ys; the effect of violating any "shall" requirement for a Y, is simply
to make an X not be a Y even if it otherwise would have been one.  If an X
is not a Y, for reasons other than a particular "shall" requirements, the
"shall" requirement will have no effect.

What complicates things with the Standard is that it applies "shall" to
source files in ways that have effects other than determining conformance.
In some cases, a "shall" statement applied to programs is used to mandate
requirements upon implementations (implementations are not required to
diagnose all possible non-conforming programs, but are required to diagnose
some), and in some cases a "shall" will releases implementations from what
would otherwise be requirements.

A "shall" in the definition of a language construct would imply that a
piece of source code which violates the condition *is not* the construct
thus described.  Given a piece of code like:

    void test(int mode)
    {
      char foo[(1,2)];
      switch(mode)
      {
        char bar[sizeof foo];
        case 1:        
        ...
      }
    }

would a diagnostic be required?  If so, where?  The declaration of "foo"
violates the "constraint" that an Integer Constant Expression shall not
contain a comma operator, but there's no direct requirement that the
dimension of "foo" be an ICE.

The expression "sizeof foo" does not contain any comma operators, and a
compiler might be able to figure out that that its value will always be
2.  That would suggest that a compiler could at its option interpret it
as an ICE, and thus "bar" may or may not be a VLA, based upon whether the
compiler does so.

[toc] | [prev] | [next] | [standalone]


#112643

FromManfred <invalid@invalid.add>
Date2017-06-20 00:00 +0200
Message-ID<oi9hi4$1jep$1@gioia.aioe.org>
In reply to#112593
On 06/19/2017 05:53 PM, Ben Bacarisse wrote:
> David Brown <david.brown@hesbynett.no> writes:
> 
<snip>

>>> But I don't see why:
>>>
>>>    p = (a,b,0);
>>>
>>> can't be well-behaved. You evaluate a and b, then assign 0 to pointer p.
>>> The language doesn't like it because implementing it is awkward (the
>>> null-pointer-constant-ness of the terminal 0 doesn't propagate up in the
>>> same way as the type of it would).
>>
>> No, the language does not like it because the sequence points spoil the
>> special nature of the a pointer constant - there needs to be some rules
>> to say when 0 is an int, and when it is a null pointer constant.
> 
> Sequence points have nothing to do with it.  For one thing, a sequence
> point is a run-time notion.  But consider 1 && 0.  It is a valid null
> pointer constant despite the sequence point.
> 
<snip>
> 
> gcc complains about using (1,0) as a null pointer constant but I don't
> see what grounds it has for doing that.
> 
>> You can write:
>>
>> 	p = (a, b, (void*) 0);
>>
>> You can also write:
>>
>> 	p = (a, b, NULL);
>>
>> That is one of the purposes of having the NULL macro - it is /always/ a
>> null pointer constant.
> 
> That makes no difference at all: NULL may always be a null pointer
> constant but then so is 0.
This may be true as long as the standard is strictly read (I take your 
word for it), but I think there is a big difference in terms of the 
rationale behind it:
C is a strongly typed language (less than C++, but more than many other 
languages), which means that it has well-defined rules for what is the 
type of a constant or expression, and it also has well-defined rules for 
how types are converted (cast, either implicitly or explicitly) from one 
to another.
Now, 0 is an exception to this rule, in that it can be /either/ a 
integer constant, /or/ a null pointer constant.
Or, in terms more strictly close to the standard's wording, an integer 
constant (expression) /in the special case/ of having value 0, can be 
/also/ used as a null pointer constant.
In any case, there is for 0 an exception to the general well-defined 
type rules in the language, and, like most exceptions, it raises 
problems when such rules must (or are wanted to) be enforced, like e.g. 
for compiler writers, but also for a programming style that would rely 
heavily on type checking.

IIRC, I had even read in some book back in the early '90s something like 
that the formal way to define a null pointer would be
void* p = (void*)0;
but "most compilers would allow" for the more compact
void* p = 0;
in the special case of 0, because it was long commonly used (and 
obviously still is).

This is to say that, even if the standard has managed to specify all of 
this in a formally correct way, and in this respect it is well written, 
there is a deviation here from the general type rules of the language, 
which explains why the examples indicated by the OP gave surprising results.

It might be worth recalling, at the risk of triggering some passionate 
feedback, that it is exactly to provide an answer to this kind of 
trouble that C++ introduced the keyword nullptr.


   What matters is the rest of the expression.
> (int *)NULL is not a null pointer constant and (1,NULL) may or may not
> be depending on how NULL is defined.
> 
> Your first example is now a valid assignment for other reasons, even if
> a and b make the expression non-constant, and the second one will be
> depending on how NULL is defined and the constant (or otherwise) nature
> of a and b.
> 
> <snip>
> 

[toc] | [prev] | [next] | [standalone]


#112646

FromKeith Thompson <kst-u@mib.org>
Date2017-06-19 15:27 -0700
Message-ID<lnd19zehps.fsf@kst-u.example.com>
In reply to#112643
Manfred <invalid@invalid.add> writes:
[...]
> This may be true as long as the standard is strictly read (I take your 
> word for it), but I think there is a big difference in terms of the 
> rationale behind it:
> C is a strongly typed language (less than C++, but more than many other 
> languages), which means that it has well-defined rules for what is the 
> type of a constant or expression, and it also has well-defined rules for 
> how types are converted (cast, either implicitly or explicitly) from one 
> to another.

A terminology quibble: A conversion may be either implicit or explicit.
A cast is an explicit conversion.  There is no such thing as an implicit
cast.

> Now, 0 is an exception to this rule, in that it can be /either/ a 
> integer constant, /or/ a null pointer constant.

0 *is* an integer constant, and it *is* a null pointer constant.

> Or, in terms more strictly close to the standard's wording, an integer 
> constant (expression) /in the special case/ of having value 0, can be 
> /also/ used as a null pointer constant.
> In any case, there is for 0 an exception to the general well-defined 
> type rules in the language, and, like most exceptions, it raises 
> problems when such rules must (or are wanted to) be enforced, like e.g. 
> for compiler writers, but also for a programming style that would rely 
> heavily on type checking.

No, there's no exception to the type rules.  The constant 0 is always of
type int.  The key think to remember is that a *null pointer constant*
is not necessarily of pointer type.  It is an expression that can be
*converted* (either implicitly, or explicitly via a cast) to a pointer
type, with the guarantee that the result of the conversion is the null
pointer value for that type.

> IIRC, I had even read in some book back in the early '90s something like 
> that the formal way to define a null pointer would be
> void* p = (void*)0;
> but "most compilers would allow" for the more compact
> void* p = 0;
> in the special case of 0, because it was long commonly used (and 
> obviously still is).

Both are guaranteed to store a null pointer value in p.  Neither is more
or less formal than the other.  Perhaps the "most compilers would allow"
phrasing was intended to allow for pre-ANSI compilers.

> This is to say that, even if the standard has managed to specify all of 
> this in a formally correct way, and in this respect it is well written, 
> there is a deviation here from the general type rules of the language, 
> which explains why the examples indicated by the OP gave surprising results.

I don't think so.  I believe the standard's discussion of null
pointers and null pointer constants is consistent and correct,
and is consistent with the general type rules of the language.
The null pointer constant rules in particular merely add some cases
where pointer conversions may be done, and what value they yield.

> It might be worth recalling, at the risk of triggering some passionate 
> feedback, that it is exactly to provide an answer to this kind of 
> trouble that C++ introduced the keyword nullptr.

I certainly wouldn't have minded if C had defined a nullptr keyword
from the beginning, and made it the only valid null pointer constant.
(Except that there's an advantage in treating the null pointer as
"zero", so that for example { 0 } works as an initializer for any
type that can be initialized.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#112647

Fromsupercat@casperkitty.com
Date2017-06-19 16:38 -0700
Message-ID<11db4c68-e1e3-4684-a36c-acc2be63ee5f@googlegroups.com>
In reply to#112646
On Monday, June 19, 2017 at 5:27:34 PM UTC-5, Keith Thompson wrote:
> I certainly wouldn't have minded if C had defined a nullptr keyword
> from the beginning, and made it the only valid null pointer constant.
> (Except that there's an advantage in treating the null pointer as
> "zero", so that for example { 0 } works as an initializer for any
> type that can be initialized.)

While one might question whether zero and NULL should be interchangeable in
other contexts, being able to use {0} a shortcut to default-initialize all
integers, floats, and pointers within an aggregate seems much cleaner than
having to select among 0, 0.0, 0.0f, and NULL based upon the type of the
first member.  It's similarly useful to be able to test for the non-nullity
of a pointer in a conditional expression rather than testing whether it
happens to be equal to the value NULL.  I'm not so keen on the implicit
comparison that's involved when assigning a pointer to a one particular
integer type (_Bool), but there's a lot about that type I don't really like.

[toc] | [prev] | [next] | [standalone]


#112648

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2017-06-20 01:14 +0100
Message-ID<87y3snbjmh.fsf@bsb.me.uk>
In reply to#112646
Keith Thompson <kst-u@mib.org> writes:
<snip>
> I certainly wouldn't have minded if C had defined a nullptr keyword
> from the beginning, and made it the only valid null pointer constant.
> (Except that there's an advantage in treating the null pointer as
> "zero", so that for example { 0 } works as an initializer for any
> type that can be initialized.)

I imagine that a language like C, but with nullptr from the start, would
probably have come up with something like {} as the universal
initializer.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#112676

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2017-06-20 12:03 +0100
Message-ID<87mv92c453.fsf@bsb.me.uk>
In reply to#112648
ram@zedat.fu-berlin.de (Stefan Ram) writes:
<snip>
>   In »_Generic«, AFAIK, »0« never is interpreted as a having
>   a pointer type.

That's right, for the simple reason that it never has pointer type!  A
lot of the discussion has get tied up in the type of things, but the
type of an expression in C is very simple to determine.  0, as an
expression has type int, always.

Some syntactic forms, whilst having type int, also have a property of
being a NPC.  A NPC is permitted in several interesting places where
other expression with type int would not be permitted.  I think it
confuses things to suggest that 0, say, is being interpreted as having
pointer type.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#112677

FromManfred <noname@invalid.add>
Date2017-06-20 13:16 +0200
Message-ID<oib06v$1jba$1@gioia.aioe.org>
In reply to#112646
On 6/20/2017 12:27 AM, Keith Thompson wrote:
> Manfred <invalid@invalid.add> writes:
> [...]
>> This may be true as long as the standard is strictly read (I take your
>> word for it), but I think there is a big difference in terms of the
>> rationale behind it:
>> C is a strongly typed language (less than C++, but more than many other
>> languages), which means that it has well-defined rules for what is the
>> type of a constant or expression, and it also has well-defined rules for
>> how types are converted (cast, either implicitly or explicitly) from one
>> to another.
> 
> A terminology quibble: A conversion may be either implicit or explicit.
> A cast is an explicit conversion.  There is no such thing as an implicit
> cast.
Fair enough.

> 
>> Now, 0 is an exception to this rule, in that it can be /either/ a
>> integer constant, /or/ a null pointer constant.
> 
> 0 *is* an integer constant, and it *is* a null pointer constant.
That's my point: 0 has (is of) two types (at a basic view, see below why 
considering it of a single type looks weird to me)

> 
>> Or, in terms more strictly close to the standard's wording, an integer
>> constant (expression) /in the special case/ of having value 0, can be
>> /also/ used as a null pointer constant.
>> In any case, there is for 0 an exception to the general well-defined
>> type rules in the language, and, like most exceptions, it raises
>> problems when such rules must (or are wanted to) be enforced, like e.g.
>> for compiler writers, but also for a programming style that would rely
>> heavily on type checking.
> 
> No, there's no exception to the type rules.  The constant 0 is always of
> type int.  The key think to remember is that a *null pointer constant*
> is not necessarily of pointer type.
Well, this may formally work (indeed it does work in standardese), but 
to me it is a clear source for potential confusion: if "a null /pointer/ 
constant is not necessarily of /pointer/ type" then my basic view on 
type rules would see something weird.

   It is an expression that can be
> *converted* (either implicitly, or explicitly via a cast) to a pointer
> type, with the guarantee that the result of the conversion is the null
> pointer value for that type.
> 
>> IIRC, I had even read in some book back in the early '90s something like
>> that the formal way to define a null pointer would be
>> void* p = (void*)0;
>> but "most compilers would allow" for the more compact
>> void* p = 0;
>> in the special case of 0, because it was long commonly used (and
>> obviously still is).
> 
> Both are guaranteed to store a null pointer value in p.  Neither is more
> or less formal than the other.  Perhaps the "most compilers would allow"
> phrasing was intended to allow for pre-ANSI compilers.
Probably so, it was old times.

> 
>> This is to say that, even if the standard has managed to specify all of
>> this in a formally correct way, and in this respect it is well written,
>> there is a deviation here from the general type rules of the language,
>> which explains why the examples indicated by the OP gave surprising results.
> 
> I don't think so.  I believe the standard's discussion of null
> pointers and null pointer constants is consistent and correct,
> and is consistent with the general type rules of the language.
> The null pointer constant rules in particular merely add some cases
> where pointer conversions may be done, and what value they yield.
Here too, that's my point: the fact that in the /specific/ case of 0 
there is a specific case for implicit conversion, which is an exception 
with respect to all other integer constants.

Don't understand me wrong, I am not complaining about 0 for null 
pointers. I know how this works and I am fine with it.
I see it as an exception to general type rules, and to me exceptions to 
rules carry some cost. It may well be the case that in this case such a 
cost is paid off by other benefits, like the one you are referring to below.

> 
>> It might be worth recalling, at the risk of triggering some passionate
>> feedback, that it is exactly to provide an answer to this kind of
>> trouble that C++ introduced the keyword nullptr.
> 
> I certainly wouldn't have minded if C had defined a nullptr keyword
> from the beginning, and made it the only valid null pointer constant.
> (Except that there's an advantage in treating the null pointer as
> "zero", so that for example { 0 } works as an initializer for any
> type that can be initialized.)
> 

[toc] | [prev] | [next] | [standalone]


#112679

Fromjameskuyper@verizon.net
Date2017-06-20 05:34 -0700
Message-ID<3971d545-204a-4fa8-b7b8-0ab29caf5164@googlegroups.com>
In reply to#112677
On Tuesday, June 20, 2017 at 7:17:03 AM UTC-4, Manfred wrote:
> On 6/20/2017 12:27 AM, Keith Thompson wrote:
...
> > 0 *is* an integer constant, and it *is* a null pointer constant.
> That's my point: 0 has (is of) two types (at a basic view, see below why 
> considering it of a single type looks weird to me)

The key point is that "null pointer constant" (NPC) is NOT a type. An NPC can
have any integer type, or it can have the type (void*), and most expressions of
those types do NOT qualify as NPCs. If an NPC occurs in certain contexts, it is implicitly converted into a pointer of the appropriate type, which is, in general, a different type depending upon the context.

...
> > I don't think so.  I believe the standard's discussion of null
> > pointers and null pointer constants is consistent and correct,
> > and is consistent with the general type rules of the language.
> > The null pointer constant rules in particular merely add some cases
> > where pointer conversions may be done, and what value they yield.
> Here too, that's my point: the fact that in the /specific/ case of 0 
> there is a specific case for implicit conversion, which is an exception 
> with respect to all other integer constants.

It's an exception with respect to all other address constants of type void*, too.

> Don't understand me wrong, I am not complaining about 0 for null 
> pointers. I know how this works and I am fine with it.
> I see it as an exception to general type rules, and to me exceptions to 
> rules carry some cost.

The following expressions: '\0', 0, 0U, 0L, 0LU, 5-5, (void*)0, (void*)(1*2-2), have the types int, int, unsigned, long, unsigned long, int, void* and void*, respectively. However, the relevant rule says that if any of those expressions are found in any of the following three contexts:

    6.3.2.3p3: cast to a pointer type
    6.5.9p2: equality or inequality comparison with a pointer value.
    6.5.15p3: 2nd or 3rd operand of ?:, where the other one is a pointer value.

then it is converted to a null pointer of the corresponding type. In all other contexts, it behaves as an ordinary constant of the type I listed above.

Now, how it does help to think of such expressions as having a different type? Keep in mind that an NPC qualifies as a pointer value for the purposes of 6.5.9p2 and 6.5.15p3 only if it has the type void*, so NULL==NULL is not necessarily a pointer comparison, it could be an unsigned long comparison. The expression x>0 ? NULL : NULL does not necessarily have a pointer type, it could have the type int.

[toc] | [prev] | [next] | [standalone]


#112695

FromKeith Thompson <kst-u@mib.org>
Date2017-06-20 08:49 -0700
Message-ID<lntw3ad5h5.fsf@kst-u.example.com>
In reply to#112677
Manfred <noname@invalid.add> writes:
> On 6/20/2017 12:27 AM, Keith Thompson wrote:
>> Manfred <invalid@invalid.add> writes:
[...]
>>> Now, 0 is an exception to this rule, in that it can be /either/ a
>>> integer constant, /or/ a null pointer constant.
>>
>> 0 *is* an integer constant, and it *is* a null pointer constant.
> That's my point: 0 has (is of) two types (at a basic view, see below
> why considering it of a single type looks weird to me)

No, 0 has one and only one type, and that type is int.  In:
    double *p;
    p = 0;
0 is a null pointer constant of type int, and it's implicitly converted
from int to double*.

A null pointer constant is not necessarily a constant, and is not
necessarily of pointer type.

Yes, that's a bit weird.  It's also true.

[...]

> Well, this may formally work (indeed it does work in standardese), but
> to me it is a clear source for potential confusion: if "a null
> /pointer/ constant is not necessarily of /pointer/ type" then my basic
> view on type rules would see something weird.

The standard's definition of "null pointer constant" is clear and
unambiguous.  It only becomes confusing if you assume that it must be of
pointer type.  (It also is neither, holy, nor Roman, nor an empire.)

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#112704

FromIke Naar <ike@iceland.freeshell.org>
Date2017-06-20 16:35 +0000
Message-ID<slrn3vfsokijst.bel.ike@iceland.freeshell.org>
In reply to#112646
On 2017-06-19, Keith Thompson <kst-u@mib.org> wrote:
> Manfred <invalid@invalid.add> writes:
> [...]
>> This may be true as long as the standard is strictly read (I take your 
>> word for it), but I think there is a big difference in terms of the 
>> rationale behind it:
>> C is a strongly typed language (less than C++, but more than many other 
>> languages), which means that it has well-defined rules for what is the 
>> type of a constant or expression, and it also has well-defined rules for 
>> how types are converted (cast, either implicitly or explicitly) from one 
>> to another.
>
> A terminology quibble: A conversion may be either implicit or explicit.
> A cast is an explicit conversion.  There is no such thing as an implicit
> cast.
>
>> Now, 0 is an exception to this rule, in that it can be /either/ a 
>> integer constant, /or/ a null pointer constant.
>
> 0 *is* an integer constant, and it *is* a null pointer constant.

It surely is an /integer constant/ (see 6.4.4.1), but, after having
been exposed to the wondrous wordings of 6.6p6, one starts to wonder
whether 0 is a /null pointer constant/. In order to qualify as such, it
must, at least, qualify as an /integer constant expression/.

Okay, 0 does qualify as a constant expression (it can be derived
grammatically from a constant-expression (6.6), it evaluates to a
constant that is in the range of representable values for its type
(6.6p4)), but the question is whether it only has operands that
are integer constants etc. (6.6p6).

Does the expression 0 have operands at all? Acording to 6.4.6p2,
an operand is defined as an entity on which an operator acts.

But the expression 0 does not have an operator, so how can it have
something on which the nonexisting operator acts?

I'm starting to get confused. I am pretty sure the intention of the
standard is that 0 is a null pointer constant, but does it follow
from the words?

[toc] | [prev] | [next] | [standalone]


#112707

From"James R. Kuyper" <jameskuyper@verizon.net>
Date2017-06-20 13:07 -0400
Message-ID<5daa866b-c5e6-53b3-fad2-dd08b7404faa@verizon.net>
In reply to#112704
On 06/20/2017 12:35 PM, Ike Naar wrote:
...
> It surely is an /integer constant/ (see 6.4.4.1), but, after having
> been exposed to the wondrous wordings of 6.6p6, one starts to wonder
> whether 0 is a /null pointer constant/. In order to qualify as such, it
> must, at least, qualify as an /integer constant expression/.
>
> Okay, 0 does qualify as a constant expression (it can be derived
> grammatically from a constant-expression (6.6), it evaluates to a
> constant that is in the range of representable values for its type
> (6.6p4)), but the question is whether it only has operands that
> are integer constants etc. (6.6p6).

6.6p6 imposes restrictions on what operands are permitted, but does not 
require that there be any operands, so that's not a problem. What is a 
problem is that an expression containing no operands is not required to 
be any of the items listed in 6.6p6. Given "int zero=0;", then 'zero' 
qualifies. I'm quite sure that this does not represent the committee's 
intent, nor is this the way that any real-world implementation handles 
such code.

It's a definition failure comparable to the one for "expression": "An 
expression is a sequence of operators and operands that specifies 
computation of a value, or that designates an object or a function, or 
that generates side effects, or that performs a combination thereof." 
(6.5p1). Something that parses as an expression according to the grammar 
(6.17p1) can fail to qualify as an expression according to 6.5p1, if it 
contains no operators, and therefore no operands. This applies to all 
identifiers, constants, and string literals.

The standard does not define the term "operand". These two clauses seem 
to have been written by someone who believes that a primary-expression 
that contains no operators can still qualify as an operand. That's 
completely inconsistent with my understanding of the term, but it would 
render both 6.5p1 and 6.6p6 more reasonable if that were the case.

[toc] | [prev] | [next] | [standalone]


#112712

FromNick Bowler <nbowler@draconx.ca>
Date2017-06-20 17:29 +0000
Message-ID<oibm19$d5s$4@dont-email.me>
In reply to#112707
On Tue, 20 Jun 2017 13:07:09 -0400, James R. Kuyper wrote:
> 6.6p6 imposes restrictions on what operands are permitted, but does not 
> require that there be any operands, so that's not a problem. What is a 
> problem is that an expression containing no operands is not required to 
> be any of the items listed in 6.6p6. Given "int zero=0;", then 'zero' 
> qualifies. I'm quite sure that this does not represent the committee's 
> intent, nor is this the way that any real-world implementation handles 
> such code.

I think it's a bit of a stretch.  The expression zero involves an lvalue
conversion when it is evaluated, so for zero to be a constant expression
you would have to consider lvalue conversion to be something that "can
be evaluated at translation time".

But lvalue conversion involves access to an object, which is a concept
that exists only in the execution environment.

[toc] | [prev] | [next] | [standalone]


#112713

From"James R. Kuyper" <jameskuyper@verizon.net>
Date2017-06-20 13:55 -0400
Message-ID<b36a677a-6e1f-bbe2-0925-c4d99f28c039@verizon.net>
In reply to#112712
On 06/20/2017 01:29 PM, Nick Bowler wrote:
> On Tue, 20 Jun 2017 13:07:09 -0400, James R. Kuyper wrote:
>> 6.6p6 imposes restrictions on what operands are permitted, but does not
>> require that there be any operands, so that's not a problem. What is a
>> problem is that an expression containing no operands is not required to
>> be any of the items listed in 6.6p6. Given "int zero=0;", then 'zero'
>> qualifies. I'm quite sure that this does not represent the committee's
>> intent, nor is this the way that any real-world implementation handles
>> such code.
>
> I think it's a bit of a stretch.  The expression zero involves an lvalue
> conversion when it is evaluated, so for zero to be a constant expression
> you would have to consider lvalue conversion to be something that "can
> be evaluated at translation time".
>
> But lvalue conversion involves access to an object, which is a concept
> that exists only in the execution environment.

6.6p6 defines an integer constant expression without referencing the 
concepts of "lvalue conversion", or "access to an object".

Those concepts are obviously the reason for the restriction to "integer 
constants, enumeration constants, character constants, sizeof 
expressions whose results are integer constants, and floating constants 
that are the immediate operands of casts", and imposing that requirement 
on an integer constant expression (ICE) as a whole would have been 
sufficient to cover "0". However, 6.6p6 has been incorrectly worded to 
apply those restrictions only to operands within an ICE, which means 
that those restrictions don't apply to an expression that has no 
operators, and therefore no operands.

It's just an error in the wording of the standard - there's no need to 
justify it by inferring additional requirements that are not actually 
stated anywhere.

[toc] | [prev] | [next] | [standalone]


#112715

FromNick Bowler <nbowler@draconx.ca>
Date2017-06-20 18:06 +0000
Message-ID<oibo7d$oar$1@dont-email.me>
In reply to#112713
On Tue, 20 Jun 2017 13:55:27 -0400, James R. Kuyper wrote:
> On 06/20/2017 01:29 PM, Nick Bowler wrote:
>> On Tue, 20 Jun 2017 13:07:09 -0400, James R. Kuyper wrote:
>>> 6.6p6 imposes restrictions on what operands are permitted, but does not
>>> require that there be any operands, so that's not a problem. What is a
>>> problem is that an expression containing no operands is not required to
>>> be any of the items listed in 6.6p6. Given "int zero=0;", then 'zero'
>>> qualifies. I'm quite sure that this does not represent the committee's
>>> intent, nor is this the way that any real-world implementation handles
>>> such code.
>>
>> I think it's a bit of a stretch.  The expression zero involves an lvalue
>> conversion when it is evaluated, so for zero to be a constant expression
>> you would have to consider lvalue conversion to be something that "can
>> be evaluated at translation time".
>>
>> But lvalue conversion involves access to an object, which is a concept
>> that exists only in the execution environment.
> 
> 6.6p6 defines an integer constant expression without referencing the 
> concepts of "lvalue conversion", or "access to an object".

The definition in 6.6p6 is clearly defining integer constant expression as
a particular type of constant expression, so all the other paragraphs under
heading 6.6 which cover constant expressions also apply, in particular 6.6p1
and 6.6p2.  You can't just ignore them and consider 6.6p6 in isolation, the
entire definition makes no sense at all otherwise.

[toc] | [prev] | [next] | [standalone]


#112721

From"James R. Kuyper" <jameskuyper@verizon.net>
Date2017-06-20 14:42 -0400
Message-ID<30dff5fb-5011-86f6-2e53-0d411a39652a@verizon.net>
In reply to#112715
On 06/20/2017 02:06 PM, Nick Bowler wrote:
> On Tue, 20 Jun 2017 13:55:27 -0400, James R. Kuyper wrote:
>> On 06/20/2017 01:29 PM, Nick Bowler wrote:
>>> On Tue, 20 Jun 2017 13:07:09 -0400, James R. Kuyper wrote:
>>>> 6.6p6 imposes restrictions on what operands are permitted, but does not
>>>> require that there be any operands, so that's not a problem. What is a
>>>> problem is that an expression containing no operands is not required to
>>>> be any of the items listed in 6.6p6. Given "int zero=0;", then 'zero'
>>>> qualifies. I'm quite sure that this does not represent the committee's
>>>> intent, nor is this the way that any real-world implementation handles
>>>> such code.
>>>
>>> I think it's a bit of a stretch.  The expression zero involves an lvalue
>>> conversion when it is evaluated, so for zero to be a constant expression
>>> you would have to consider lvalue conversion to be something that "can
>>> be evaluated at translation time".
>>>
>>> But lvalue conversion involves access to an object, which is a concept
>>> that exists only in the execution environment.
>>
>> 6.6p6 defines an integer constant expression without referencing the
>> concepts of "lvalue conversion", or "access to an object".
>
> The definition in 6.6p6 is clearly defining integer constant expression as
> a particular type of constant expression, so all the other paragraphs under
> heading 6.6 which cover constant expressions also apply, in particular 6.6p1
> and 6.6p2.  You can't just ignore them and consider 6.6p6 in isolation, the
> entire definition makes no sense at all otherwise.

My point is that it doesn't make sense even in context: it imposes a 
restriction that is clearly intended to apply to expressions that have 
no operators, and therefore no operands, but expresses that restriction 
as applying only to operands. Appealing to the context only highlights 
that error, it doesn't remove it. If the context were sufficient to 
impose that same restriction even when there are no operands, it would 
be unnecessary to state that restriction; it would inherently apply to 
operands, too.

Same comment, but more specific: if "zero" were disallowed for the 
reasons you give, then "zero*10" would also be disallowed for the same 
reasons; there would be no need to explicitly restrict operands to 
"integer constants, floating constants, enumeration constants, character 
constants, and sizeof expressions whose results are integer constants".

[toc] | [prev] | [next] | [standalone]


#112726

FromNick Bowler <nbowler@draconx.ca>
Date2017-06-20 19:10 +0000
Message-ID<oibrv9$oar$3@dont-email.me>
In reply to#112721
On Tue, 20 Jun 2017 14:42:38 -0400, James R. Kuyper wrote:
> On 06/20/2017 02:06 PM, Nick Bowler wrote:
>> On Tue, 20 Jun 2017 13:55:27 -0400, James R. Kuyper wrote:
[...]
>>> 6.6p6 defines an integer constant expression without referencing the
>>> concepts of "lvalue conversion", or "access to an object".
>>
>> The definition in 6.6p6 is clearly defining integer constant expression as
>> a particular type of constant expression, so all the other paragraphs under
>> heading 6.6 which cover constant expressions also apply, in particular 6.6p1
>> and 6.6p2.  You can't just ignore them and consider 6.6p6 in isolation, the
>> entire definition makes no sense at all otherwise.
> 
> My point is that it doesn't make sense even in context: it imposes a 
> restriction that is clearly intended to apply to expressions that have 
> no operators, and therefore no operands, but expresses that restriction 
> as applying only to operands.

It doesn't matter.  When there are no operators or operands the only
restriction is that it is a constant expression with integer type --
this is sufficient.

Otherwise, we have an operator, so the restrictions apply.  Here's some
examples of constant expressions where the restrictions in 6.6p6 matter:

  (int)"hello"

This is a constant expression with integer type but it is NOT an integer
constant expression because it violates the operand restriction (and also
the cast operator restriction).

Here's another:

  extern int a[];
  &a[0] - &a[0]

This is a constant expression with integer type but it is NOT an integer
constant expression: the operands of the - operator don't fit the bill
(not one of the items listed in 6.6p6).

There is only a minor problem with the wording in that other integer
constant expressions should be explicitly permitted as operands, because
this one:

  1 + (2 + 3)

is a constant expression with integer type that presumably should
be an integer constant expression too (an implementations treat it
as one).  But (2 + 3) is an operand that does not fit the restrictions
of 6.6p6.  This appears to an oversight.

> Same comment, but more specific: if "zero" were disallowed for the 
> reasons you give, then "zero*10" would also be disallowed for the same 
> reasons.

Sure.  Notwithstanding 6.6p10, zero*10 is not a constant expression so
it is certainly not an integer constant expression either.  We don't
even need to look at the further restrictions in 6.6p6.

[toc] | [prev] | [next] | [standalone]


#112719

FromIke Naar <ike@iceland.freeshell.org>
Date2017-06-20 18:31 +0000
Message-ID<slrn3vfsokiqme.eci.ike@iceland.freeshell.org>
In reply to#112707
On 2017-06-20, James R. Kuyper <jameskuyper@verizon.net> wrote:
> The standard does not define the term "operand".

In 6.4.6p2, the term 'operand' appears in italics in the phrase
'An /operand/ is an entity on which an operator acts'. Doesn't this
count as a definition?

[toc] | [prev] | [next] | [standalone]


Page 3 of 6 — ← Prev page 1 2 [3] 4 5 6  Next page →

Back to top | Article view | comp.lang.c


csiph-web