Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #112475 > unrolled thread
| Started by | bartc <bc@freeuk.com> |
|---|---|
| First post | 2017-06-18 17:15 +0100 |
| Last post | 2017-06-19 12:34 -0700 |
| Articles | 20 on this page of 111 — 14 participants |
Back to article view | Back to comp.lang.c
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 →
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-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]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-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]
| From | Manfred <invalid@invalid.add> |
|---|---|
| Date | 2017-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-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]
| From | Manfred <noname@invalid.add> |
|---|---|
| Date | 2017-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]
| From | jameskuyper@verizon.net |
|---|---|
| Date | 2017-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-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]
| From | Ike Naar <ike@iceland.freeshell.org> |
|---|---|
| Date | 2017-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]
| From | "James R. Kuyper" <jameskuyper@verizon.net> |
|---|---|
| Date | 2017-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]
| From | Nick Bowler <nbowler@draconx.ca> |
|---|---|
| Date | 2017-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]
| From | "James R. Kuyper" <jameskuyper@verizon.net> |
|---|---|
| Date | 2017-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]
| From | Nick Bowler <nbowler@draconx.ca> |
|---|---|
| Date | 2017-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]
| From | "James R. Kuyper" <jameskuyper@verizon.net> |
|---|---|
| Date | 2017-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]
| From | Nick Bowler <nbowler@draconx.ca> |
|---|---|
| Date | 2017-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]
| From | Ike Naar <ike@iceland.freeshell.org> |
|---|---|
| Date | 2017-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