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 5 of 6 — ← Prev page 1 2 3 4 [5] 6 Next page →
| From | bartc <bc@freeuk.com> |
|---|---|
| Date | 2017-06-21 18:09 +0100 |
| Message-ID | <uLx2B.11727$hc7.5658@fx41.am4> |
| In reply to | #112806 |
On 21/06/2017 17:54, Keith Thompson wrote: > I'd like a definition of "expression" that does not require it to > contain operators and/or operands. Simply deferring to the grammar > is one way to do that. Yeah, that grammar is so grok at a glance. Just have an informal definition of an expression that comprises terminals as well as operators and operands. Then 0 is a terminal.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-06-22 00:50 -0700 |
| Message-ID | <kfnlgok5ulr.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #112806 |
Keith Thompson <kst-u@mib.org> writes:
> Tim Rentsch <txr@alumni.caltech.edu> writes:
> [...]
>
>> In comp.lang.c there is a game some people like to play, which
>> might be called "let's pretend the meaning of English words
>> and phrases used in the Standard is single-valued (and by the
>> way uses the values that I think it should)". Usually it's
>> easy to tell when people are playing it, because there are
>> giveaway phrases like "literal meaning" or "strictly speaking"
>> or "what the words actually say" in the comments. It's a fun
>> game, and I play it myself on occasion. However, please don't
>> fall into the trap of making it more than it is, because even
>> though it's fun to play it doesn't match how the authors of
>> the Standard interpret the text.
>
> To some extent, sure, it can be a game, but that's not all it is.
> For example, when I point out that the definition of "expression"
> is flawed, I'm not arguing that 0 really isn't an expression.
> Rather, I'm advocating a change to the wording of the standard to
> reflect its intent -- and meanwhile, I accept the need to use a bit
> of common sense, using the obvious intent behind the words rather
> than the literal words themselves to determine what is and is not
> an expression.
Note the difference between the two following kinds comments:
1. Passage X can be read as saying "blah", which is not
consistent with the "bleah" that people expect.
2. Passage X can only be read as saying "blah"; the
"bleah" that some people expect is wrong.
The first is a constructive comment. The second is a game.
AFAIK the comments you make usually have more of the (1) flavor
than the (2) flavor, which fits with you generally being more
interested in being constructive than in pointless bickering
over the "true meaning" of something. (At least that is my
impression.)
>> In an expression-statement like '0;', there is no doubt that '0'
>> is an expression and also an operand within that expression.
>
> Could it be that you're playing the game yourself?
Just the opposite. What I mean is that there is no doubt that
the Standard intends that '0' is an expression and also an
operand within that expression, in the sense that 6.6 p6 refers
to those terms.
> We have two inconsistent definitions, a definition of "expression"
> that requires it to include "operands", and a definition of
> "operand", "an entity on which an operator acts". The latter seems
> clear, unambiguous, and consistent with the usual English meaning of
> the word -- which suggests that it's the definition of "expression"
> that needs to be fixed.
I don't agree with the first part of the last sentence, but I
also think it's pointless to argue about it. For me it's enough
to say that the definition of "expression" can be read in more
than one way (which seems obviously true, since different people
do read it differently), and it would be nice if that could be
clarified.
> I have no doubt that 0 is an expression. I do not believe that, if it
> appears as a full expression, it is an "operand", nor do I think it's
> useful to invent a mythical implicit "operator" to make it one.
>
> On the other hand, the term "operand" could be redefined, but I
> don't think that's the simplest and clearest solution.
>
> I'd like a definition of "expression" that does not require it to
> contain operators and/or operands. Simply deferring to the grammar
> is one way to do that.
I am now resigned to the idea that many of these "trouble spots"
are never going to be addressed, for the simple reason that the
people who actually write the Standard don't think of them as
problems (ie, in many or most cases). IMO it would be more
productive to focus on just the most extreme cases, and let the
others pass only with a minor note and then forget about them.
>> For 6.6 p6, it might seem like "operand" is being used in a way
>> that is not consistent with its definition.
>
> The definition of "constant expression" also needs some work, I think.
> On the other hand, I've read that definition before and not noticed
> the problems; I subconsciously glossed over the inconsistencies.
My test is something like this: how often or how likely is there
misunderstanding? In the case of constant expressions and ICEs I
believe those numbers are pretty low. To me that says these
passages are pretty low on the totem pole in terms of worrying
about fixing them.
>> What is actually
>> going on is more subtle. In most cases where the Standard uses
>> "operand" there is an abuse of language going on. Consider an
>> expression like '1+2*3'. The operator '+' does not "act on" the
>> expression '2*3'. Rather the operation of addition "acts on" the
>> result of evaluating '2*3'. There is an inherent ambiguity
>> between results at runtime and their corresponding syntactic
>> forms at translation time.
>
> Yes, glossing over the distinction between constructs that appear
> in C source and/or at compile time vs. constructs that exist at run
> time is very common, and may be nearly inevitable. Describing the
> language in a way that always makes that distinction clearly might
> be an interesting challange. Doing so in a way that's legible to
> a typical reader would be even more so.
Furthermore it isn't obvious that such a change would necessarily be
an improvement. There is a tradeoff between being understandable
and being formally correct. A decision about whether the text
should be revised needs to take into account a balance between these
two opposing forces, not just one or the other.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-06-19 10:24 -0700 |
| Message-ID | <lnvanrgabv.fsf@kst-u.example.com> |
| In reply to | #112557 |
David Brown <david.brown@hesbynett.no> writes:
[...]
> Should (x ? 0 : 0) be considered the int constant 0, the null pointer
> constant, or should the decision be left to constraint fitting on the
> rest of the expression (in this case, the assignment)?
(x ? 0 : 0) is a constant expression if and only if x is a constant
expression.
Given:
int x = 42;
(x ? 0 : 0);
we can determine that the expression is of type int with the value 0,
but it's not a constant expression. Consider the case where x is
volatile, so evaluating it has side effects. Or consider replacing x by
a function call. The definition of a constan expression does not
distinguish between non-constant subexpressions with side effects and
non-constant subexpressions without side effects.
The definition of "constant expression" isn't intended to cover all
cases where the result of an expression *can* be determined at compile
time. It's intended to be reasonably simple, so that all compilers can
be required to implement it correctly. There are cases where an
expression whose value *could* be determined at compile time are not
treated as constant expressions, but that's not much of an inconvenience
in practice.
[...]
--
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-19 22:32 -0700 |
| Message-ID | <kfn1sqf8bru.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #112601 |
Keith Thompson <kst-u@mib.org> writes: > David Brown <david.brown@hesbynett.no> writes: > [...] > >> Should (x ? 0 : 0) be considered the int constant 0, the null pointer >> constant, or should the decision be left to constraint fitting on the >> rest of the expression (in this case, the assignment)? > > (x ? 0 : 0) is a constant expression if and only if x is a constant > expression. > > Given: > > int x = 42; > (x ? 0 : 0); > > we can determine that the expression is of type int with the value 0, > but it's not a constant expression. Consider the case where x is > volatile, so evaluating it has side effects. Or consider replacing x by > a function call. The definition of a constan expression does not > distinguish between non-constant subexpressions with side effects and > non-constant subexpressions without side effects. > > The definition of "constant expression" isn't intended to cover all > cases where the result of an expression *can* be determined at compile > time. [...] Notice that the Standard doesn't talk about the result of an expression being determined (at compile time). A constant expression is one that "can be evaluated during translation rather than runtime". Strictly speaking the expression (x ? 0 : 0) cannot be evaluated during translation, because the object for 'x' does not then exist. That means the required lvalue conversion cannot be performed, which in turn means the expression cannot be evaluated. Let me be clear that this is a legalistic argument, and the meaning intended by the Standard might be different.
[toc] | [prev] | [next] | [standalone]
| From | bartc <bc@freeuk.com> |
|---|---|
| Date | 2017-06-19 19:40 +0100 |
| Message-ID | <7UU1B.186652$Gx3.8203@fx45.am4> |
| In reply to | #112557 |
On 19/06/2017 13:39, David Brown wrote: > On 19/06/17 14:05, bartc wrote: >> I don't want to do any more work than is necessary. > > Who does? But you need to do the work that /is/ necessary. > >> >> If X is needed to implement a feature properly or to diagnose an error, >> but only some compilers bother, then I won't either. > > You are aiming to be the lowest of all compilers, with the least > features and the most bugs? The original concept was for an all-in-one whole-project compiler which processes and executes all the source code for an application at once. That requires some interesting new approaches, so I don't want to get bogged down in the details of implementing every single aspect of C, as that would take years. Only what's necessary for typical projects. (What exists at the minute is an interim version that works more traditionally.) But I will need to implement that on a different language first, before coming back and applying it to C. C doesn't have a built-in import system, which would help define the modules and the boundaries of a project, so that makes it a little more challenging. So no, it won't be the lowest of all the compilers, it'll just be used differently (more like Python than C). -- bartc
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-06-19 12:08 -0700 |
| Message-ID | <lnr2yfg5hs.fsf@kst-u.example.com> |
| In reply to | #112557 |
David Brown <david.brown@hesbynett.no> writes:
> On 19/06/17 14:05, bartc wrote:
[...]
>> (a,b,0) can't be an integer constant expression, even if a and b are
>> constants, because the language considers that nonsensical.
(a,b,0) isn't an integer constant expression because the language says
it isn't. The standard expresses no opinion on how sensible it would
be. (I wouldn't have any particular problem if the language permitted
comma operators in constant expressions, but forbidding them isn't a
problem either.)
> True. I suspect that is because the comma operator has a sequence
> point, and it would not make sense to have a sequence point in a
> constant expression.
A conditional expression has a sequence point between the evaluation of
the first operand and the evaluation of the second or third operand. I
think it's permitted because it can be useful in some cases,
particularly in macro expansions.
[...]
> 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.
As I've said elsethread, 0 is an expression of type int *and* a null
pointer constant.
> 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.
So is 0. Indeed NULL can be #defined simply as 0.
[...]
--
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 | bartc <bc@freeuk.com> |
|---|---|
| Date | 2017-06-19 20:32 +0100 |
| Message-ID | <BFV1B.750855$dE4.692904@fx36.am4> |
| In reply to | #112611 |
On 19/06/2017 20:08, Keith Thompson wrote: >> That is one of the purposes of having the NULL macro - it is /always/ a >> null pointer constant. > > So is 0. Indeed NULL can be #defined simply as 0. Not really. This is what prompted the thread actually, because I had an error caused by my defining NULL as 0. It came up in code like this when this macro was invoked: #define checklightudptr(L, p) \ (((uint64_t)(p) >> 47) ? (lj_err_msg(L, LJ_ERR_BADLU), NULL) : (p)) Here, the (a, NULL) pattern is used, as well as (cond ? NULL : p) When NULL is 0, then the whole thing becomes (cond ? (a,0): p), which is used to set a pointer value. Neither cond nor is a compile-time constant. (Macro is called like this: setlightudV(L->top, checklightudptr(L, p)); ) -- bartc
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-06-19 12:48 -0700 |
| Message-ID | <lny3snep2y.fsf@kst-u.example.com> |
| In reply to | #112618 |
bartc <bc@freeuk.com> writes:
> On 19/06/2017 20:08, Keith Thompson wrote:
>
>>> That is one of the purposes of having the NULL macro - it is /always/ a
>>> null pointer constant.
>>
>> So is 0. Indeed NULL can be #defined simply as 0.
>
> Not really.
Yes, really.
> This is what prompted the thread actually, because I had an
> error caused by my defining NULL as 0. It came up in code like this when
> this macro was invoked:
>
> #define checklightudptr(L, p) \
> (((uint64_t)(p) >> 47) ? (lj_err_msg(L, LJ_ERR_BADLU), NULL) : (p))
>
> Here, the (a, NULL) pattern is used, as well as (cond ? NULL : p)
>
> When NULL is 0, then the whole thing becomes (cond ? (a,0): p), which is
> used to set a pointer value.
>
> Neither cond nor is a compile-time constant.
>
> (Macro is called like this:
> setlightudV(L->top, checklightudptr(L, p));
> )
I haven't taken the time to study that macro, but if it doesn't work
correctly when NULL is #defined as 0, then it's a poorly defined macro,
or at least is not portable. Then again, casting a pointer value (p is
a pointer, yes?) to uint64_t is non-portable already.
Perhaps the author of the macro was using an implementation that defines
NULL as ((void*)0), and so didn't run into the problem you did.
--
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 | jameskuyper@verizon.net |
|---|---|
| Date | 2017-06-19 13:08 -0700 |
| Message-ID | <550860b3-c7a6-4485-a9e7-476f8e3e9bcb@googlegroups.com> |
| In reply to | #112618 |
On Monday, June 19, 2017 at 3:32:58 PM UTC-4, Bart wrote: > On 19/06/2017 20:08, Keith Thompson wrote: > > >> That is one of the purposes of having the NULL macro - it is /always/ a > >> null pointer constant. > > > > So is 0. Indeed NULL can be #defined simply as 0. > > Not really. ... The standard says it can be. Any code that won't work as intended if NULL is #defined that way is code that needs to be fixed, because defining that way is not only permitted by the standard, but that is one of the two most frequently chosen definitions for NULL. > ... This is what prompted the thread actually, because I had an > error caused by my defining NULL as 0. It came up in code like this when > this macro was invoked: > > #define checklightudptr(L, p) \ > (((uint64_t)(p) >> 47) ? (lj_err_msg(L, LJ_ERR_BADLU), NULL) : (p)) > > Here, the (a, NULL) pattern is used, as well as (cond ? NULL : p) > > When NULL is 0, then the whole thing becomes (cond ? (a,0): p), which is > used to set a pointer value. > > Neither cond nor is a compile-time constant. > > (Macro is called like this: > setlightudV(L->top, checklightudptr(L, p)); > ) You haven't made it clear what the problem is. Please explain further. Whatever the problem is, it's a problem with the #definition of the macro, or with the use of it, not with your choice of #defining NULL to be 0. A correctly-written #definition for that macro, if used correctly, should produce the desired result even when using an implementation which makes that choice - because that choice is both permitted, and popular.
[toc] | [prev] | [next] | [standalone]
| From | Nick Bowler <nbowler@draconx.ca> |
|---|---|
| Date | 2017-06-19 20:40 +0000 |
| Message-ID | <oi9csb$d5s$2@dont-email.me> |
| In reply to | #112626 |
On Mon, 19 Jun 2017 13:08:26 -0700, jameskuyper wrote:
> On Monday, June 19, 2017 at 3:32:58 PM UTC-4, Bart wrote:
[...]
>> ... This is what prompted the thread actually, because I had an
>> error caused by my defining NULL as 0. It came up in code like this when
>> this macro was invoked:
>>
>> #define checklightudptr(L, p) \
>> (((uint64_t)(p) >> 47) ? (lj_err_msg(L, LJ_ERR_BADLU), NULL) : (p))
>>
>> Here, the (a, NULL) pattern is used, as well as (cond ? NULL : p)
>>
>> When NULL is 0, then the whole thing becomes (cond ? (a,0): p), which is
>> used to set a pointer value.
>>
>> Neither cond nor is a compile-time constant.
>>
>> (Macro is called like this:
>> setlightudV(L->top, checklightudptr(L, p));
>> )
>
> You haven't made it clear what the problem is. Please explain further.
The problem seems pretty obvious. If NULL expands to 0 then the
expansion of the checklightudptr macro violates the constraints of
the ?: operator, because the 2nd operand has integer type (and is
not a null pointer constant) and the 3rd operand has pointer type.
The immediate problem is easily fixed by using (void *)0 instead of
NULL, so both operands have pointer type, one of which is a pointer
to void, satisfying the constraints.
The resulting expression will have type "pointer to [possibly qualified]
void", rather than the original type of the 2nd macro argument, which is
maybe undesired. This can be fixed too:
#define checklightudptr(L, p) \
(((uint64_t)(p) >> 47) ? (lj_err_msg(L, LJ_ERR_BADLU), 0?p:0) : (p))
Now the expansion will always have the same type as p, improving type
safety, and still doesn't depend on any particular expansion of NULL.
[toc] | [prev] | [next] | [standalone]
| From | bartc <bc@freeuk.com> |
|---|---|
| Date | 2017-06-19 22:01 +0100 |
| Message-ID | <gYW1B.304275$524.12399@fx41.am4> |
| In reply to | #112626 |
On 19/06/2017 21:08, jameskuyper@verizon.net wrote: > On Monday, June 19, 2017 at 3:32:58 PM UTC-4, Bart wrote: >> On 19/06/2017 20:08, Keith Thompson wrote: >> >>>> That is one of the purposes of having the NULL macro - it is /always/ a >>>> null pointer constant. >>> >>> So is 0. Indeed NULL can be #defined simply as 0. >> >> Not really. ... > > The standard says it can be. Any code that won't work as intended if NULL is > #defined that way is code that needs to be fixed, because defining that way is > not only permitted by the standard, but that is one of the two most frequently > chosen definitions for NULL. If NULL works as zero, why is it usually defined as ((void*)0)? >> #define checklightudptr(L, p) \ >> (((uint64_t)(p) >> 47) ? (lj_err_msg(L, LJ_ERR_BADLU), NULL) : (p)) >> >> Here, the (a, NULL) pattern is used, as well as (cond ? NULL : p) >> >> When NULL is 0, then the whole thing becomes (cond ? (a,0): p), which is >> used to set a pointer value. >> >> Neither cond nor is a compile-time constant. >> >> (Macro is called like this: >> setlightudV(L->top, checklightudptr(L, p)); >> ) > > You haven't made it clear what the problem is. Please explain further. Whatever the problem is, it's a problem with the #definition of the macro, or with the use of it, not with your choice of #defining NULL to be 0. A correctly-written #definition for that macro, if used correctly, should produce the desired result even when using an implementation which makes that choice - because that choice is both permitted, and popular. > The problem with the code that the macro expands to is illustrated here: #define Null 0 int *p, *q; int a, b; p = (a ? (b, Null) : q); gcc says: "warning: pointer/integer type mismatch in conditional expression" (And my compiler fails because it only has errors, not warnings.) If I change Null to ((void*)0), then the problem goes away. Maybe there is a problem with the source code, but if it has been tested with compilers such as gcc and MSVC, then there's nothing you can do. You can't expect people using your compiler to build other working, tested, applications to start modifying those applications. Anyway, nearly all compilers I looked at define NULL as ((void*)0), when compiling C. They only define NULL as 0 when the header is intended for C++. (The odd C compiler was Small C that defined it as 0, but that is limited anyway.) But I'd be interested in how you would change that macro so that it works even when NULL is zero. Try this simpler version: #define M(a,b,q) (a ? (b, NULL) : q) and invoke it like this: int *p, *q; int a, b; p = M(a,b,q); -- bartc
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-06-19 14:15 -0700 |
| Message-ID | <b6971b40-a443-4950-bcfe-cfac32e6a756@googlegroups.com> |
| In reply to | #112633 |
On Monday, June 19, 2017 at 4:01:07 PM UTC-5, Bart wrote:
> If NULL works as zero, why is it usually defined as ((void*)0)?
Before (void*) was added to the language, the only practical way to write
a null pointer constant that could be coerced to any type (without a cast)
was to use an integer literal zero.
On many C implementations (including, so far as I can tell, the original one
on the PDP-11), a null pointer of any type will be passed in exactly the
same way as an integer with value zero. Thus, something like:
int foo();
...
foo(NULL);
...
int foo(p)
int *p;
{
...
}
will work just fine if NULL is defined as a literal zero, without any need
for a programmer to explicitly cast NULL to (int*). Such code would not be
portable to implementations which pass types "int" and "int*" differently,
but prototypes take care of most such difficulties.
[toc] | [prev] | [next] | [standalone]
| From | jameskuyper@verizon.net |
|---|---|
| Date | 2017-06-19 14:25 -0700 |
| Message-ID | <c8af3aae-652b-43b9-b134-f2fd800eb0fc@googlegroups.com> |
| In reply to | #112633 |
On Monday, June 19, 2017 at 5:01:07 PM UTC-4, Bart wrote: > On 19/06/2017 21:08, jameskuyper@verizon.net wrote: > > On Monday, June 19, 2017 at 3:32:58 PM UTC-4, Bart wrote: ... > >>> So is 0. Indeed NULL can be #defined simply as 0. > >> > >> Not really. ... > > > > The standard says it can be. Any code that won't work as intended if NULL is > > #defined that way is code that needs to be fixed, because defining that way is > > not only permitted by the standard, but that is one of the two most frequently > > chosen definitions for NULL. > > If NULL works as zero, why is it usually defined as ((void*)0)? Because (void*)0 is, in several ways, a better definition. NULL's purpose implies that it should only be used where a pointer is needed; defining it as ((void*)0) means that any attempt to misuse it in an integer context will be a constraint violation. Both definitions are allowed, because both definitions were in common use when the first version of the standard came out. Code that was incompatible with 0, and code that was incompatible with (void*)0, were both commonplace. The committee compromised by allowing both, which means that code which is intended to be portable must be written so that it works correctly regardless of how NULL expands, as long as it expands into one of the permitted forms. If I were designing the language from scratch, I'd have made NULL a keyword rather than a macro, and functionally equivalent to ((void*)0), but no one asked me (and I certainly didn't know enough to make such a suggestion at the time the question was being decided). > >> #define checklightudptr(L, p) \ > >> (((uint64_t)(p) >> 47) ? (lj_err_msg(L, LJ_ERR_BADLU), NULL) : (p)) > >> > >> Here, the (a, NULL) pattern is used, as well as (cond ? NULL : p) > >> > >> When NULL is 0, then the whole thing becomes (cond ? (a,0): p), which is > >> used to set a pointer value.Is that a hard concept for you to understand? > >> > >> Neither cond nor is a compile-time constant. > >> > >> (Macro is called like this: > >> setlightudV(L->top, checklightudptr(L, p)); > >> ) > > > > You haven't made it clear what the problem is. Please explain further. > > Whatever the problem is, it's a problem with the #definition of the macro, > > or with the use of it, not with your choice of #defining NULL to be 0. A > > correctly-written #definition for that macro, if used correctly, should > > produce the desired result even when using an implementation which makes > > that choice - because that choice is both permitted, and popular. > > > > The problem with the code that the macro expands to is illustrated here: > Is that a hard concept for you to understand? > #define Null 0 > > int *p, *q; > int a, b; > > p = (a ? (b, Null) : q); > > gcc says: > > "warning: pointer/integer type mismatch in conditional expression" > > (And my compiler fails because it only has errors, not warnings.) > > If I change Null to ((void*)0), then the problem goes away. An alternative solution is to fix the macro, not the definition of NULL, since the macro isn't portable. > Maybe there is a problem with the source code, but if it has been tested > with compilers such as gcc and MSVC, then there's nothing you can do. > You can't expect people using your compiler to build other working, > tested, applications to start modifying those applications. You can if you want to. Other compilers have done so. C++ not only allows 0, but mandates it, and had little trouble getting away with that change. Of course, C++ now has nullptr, which is functionally close to what I would have selected, except that it's made much more complicated than it should need to be by the fact that Stroustrup made so many compromises to keep C++ compatible with C. > But I'd be interested in how you would change that macro so that it > works even when NULL is zero. Try this simpler version: > > #define M(a,b,q) (a ? (b, NULL) : q) Replace NULL with (void*)NULL
[toc] | [prev] | [next] | [standalone]
| From | Ike Naar <ike@iceland.freeshell.org> |
|---|---|
| Date | 2017-06-19 21:06 +0000 |
| Message-ID | <slrn3vfsokgfd7.8v7.ike@iceland.freeshell.org> |
| In reply to | #112611 |
On 2017-06-19, Keith Thompson <kst-u@mib.org> wrote:
> David Brown <david.brown@hesbynett.no> writes:
>> 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.
>
> So is 0. Indeed NULL can be #defined simply as 0.
Indeed it can, but it can lead to unpleasant surprises.
Consider variadic functions.
If a variadic function expects a pointer in the variable part of
the parameter list, and the caller provides a NULL argument that
expands to an unadorned 0, the NULL is interpreted as an int in
such a context, and it is not passed correctly if ints and pointers
have different sizes.
In the past I've been bitten by this with variadic functions from
the X window system that expected a list of strings (pointer to
char), terminated by a null pointer to char. If one called such a
function as
function("Martha", "my", "dear", NULL);
one would get all kinds of weird errors on an implementation that
defined NULL as plain 0, when on that platform sizeof (int) !=
sizeof (char*).
Those calls had to be changed to
function("Martha", "my", "dear", (char*) NULL);
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-06-19 14:28 -0700 |
| Message-ID | <lnpodzekg2.fsf@kst-u.example.com> |
| In reply to | #112634 |
Ike Naar <ike@iceland.freeshell.org> writes:
> On 2017-06-19, Keith Thompson <kst-u@mib.org> wrote:
>> David Brown <david.brown@hesbynett.no> writes:
>>> 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.
>>
>> So is 0. Indeed NULL can be #defined simply as 0.
>
> Indeed it can, but it can lead to unpleasant surprises.
But defining it as ((void*)0) doesn't avoid all those surprises.
> Consider variadic functions.
>
> If a variadic function expects a pointer in the variable part of
> the parameter list, and the caller provides a NULL argument that
> expands to an unadorned 0, the NULL is interpreted as an int in
> such a context, and it is not passed correctly if ints and pointers
> have different sizes.
>
> In the past I've been bitten by this with variadic functions from
> the X window system that expected a list of strings (pointer to
> char), terminated by a null pointer to char. If one called such a
> function as
>
> function("Martha", "my", "dear", NULL);
>
> one would get all kinds of weird errors on an implementation that
> defined NULL as plain 0, when on that platform sizeof (int) !=
> sizeof (char*).
>
> Those calls had to be changed to
>
> function("Martha", "my", "dear", (char*) NULL);
If the function treats its arguments as a char* or void*, then passing
an unadorned NULL should work if NULL is defined as ((void*)0). But if
the function expects, for example, an int*, then ((void*)0) is not
guaranteed to have the same representation, and may cause undefined
behavior.
If you need to pass a null pointer as a variadic argument, always cast
it to the appropriate printer type.
--
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-19 21:35 +0000 |
| Message-ID | <slrn3vfsokgh37.2h5.ike@iceland.freeshell.org> |
| In reply to | #112639 |
On 2017-06-19, Keith Thompson <kst-u@mib.org> wrote:
> Ike Naar <ike@iceland.freeshell.org> writes:
>> On 2017-06-19, Keith Thompson <kst-u@mib.org> wrote:
>>> David Brown <david.brown@hesbynett.no> writes:
>>>> 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.
>>>
>>> So is 0. Indeed NULL can be #defined simply as 0.
>>
>> Indeed it can, but it can lead to unpleasant surprises.
>
> But defining it as ((void*)0) doesn't avoid all those surprises.
>
>> Consider variadic functions.
>>
>> If a variadic function expects a pointer in the variable part of
>> the parameter list, and the caller provides a NULL argument that
>> expands to an unadorned 0, the NULL is interpreted as an int in
>> such a context, and it is not passed correctly if ints and pointers
>> have different sizes.
>>
>> In the past I've been bitten by this with variadic functions from
>> the X window system that expected a list of strings (pointer to
>> char), terminated by a null pointer to char. If one called such a
>> function as
>>
>> function("Martha", "my", "dear", NULL);
>>
>> one would get all kinds of weird errors on an implementation that
>> defined NULL as plain 0, when on that platform sizeof (int) !=
>> sizeof (char*).
>>
>> Those calls had to be changed to
>>
>> function("Martha", "my", "dear", (char*) NULL);
>
> If the function treats its arguments as a char* or void*, then passing
> an unadorned NULL should work if NULL is defined as ((void*)0). But if
> the function expects, for example, an int*, then ((void*)0) is not
> guaranteed to have the same representation, and may cause undefined
> behavior.
>
> If you need to pass a null pointer as a variadic argument, always cast
> it to the appropriate printer type.
Of course.
The danger is that, on many platforms, (void*) has the same representation
as any other pointer type, an one is easily lured into the trap of forgetting
the cast.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-06-19 14:48 -0700 |
| Message-ID | <2e553453-e40e-4b47-ad4d-dee28631d504@googlegroups.com> |
| In reply to | #112641 |
On Monday, June 19, 2017 at 4:38:59 PM UTC-5, Ike Naar wrote: > The danger is that, on many platforms, (void*) has the same representation > as any other pointer type, an one is easily lured into the trap of forgetting > the cast. When the C Standard was written, requiring that systems use the same representation for all pointers passed to variadic functions would have not only slowed things down on some platforms that would otherwise use varied representations, but it would have--more importantly--broken existing programs that designed to handle those varied representations. What fraction of programs are ever going to be called upon to run on any platform that couldn't practically use the same representation for all pointers passed to variadic functions?
[toc] | [prev] | [next] | [standalone]
| From | Ike Naar <ike@iceland.freeshell.org> |
|---|---|
| Date | 2017-06-20 15:38 +0000 |
| Message-ID | <slrn3vfsokigj7.bel.ike@iceland.freeshell.org> |
| In reply to | #112642 |
On 2017-06-19, supercat@casperkitty.com <supercat@casperkitty.com> wrote: > On Monday, June 19, 2017 at 4:38:59 PM UTC-5, Ike Naar wrote: >> The danger is that, on many platforms, (void*) has the same representation >> as any other pointer type, an one is easily lured into the trap of forgetting >> the cast. > > When the C Standard was written, requiring that systems use the same > representation for all pointers passed to variadic functions would have > not only slowed things down on some platforms that would otherwise use > varied representations, but it would have--more importantly--broken > existing programs that designed to handle those varied representations. > > What fraction of programs are ever going to be called upon to run on any > platform that couldn't practically use the same representation for all > pointers passed to variadic functions? If this question had been formulated in a different fashion, certain readers might have gotten the impression that it wasn't meant to be rhetorical, except when the possibility existed that just because the question wasn't asked asked in a such fashion might have lead to a different conclusion.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-06-19 15:16 -0700 |
| Message-ID | <lnlgonei8u.fsf@kst-u.example.com> |
| In reply to | #112641 |
Ike Naar <ike@iceland.freeshell.org> writes:
> On 2017-06-19, Keith Thompson <kst-u@mib.org> wrote:
[...]
>> If you need to pass a null pointer as a variadic argument, always cast
>> it to the appropriate printer type.
>
> Of course.
>
> The danger is that, on many platforms, (void*) has the same representation
> as any other pointer type, an one is easily lured into the trap of forgetting
> the cast.
And on many platforms (though not as many), int, void*, and other
pointer types all have the same representation, or at least are
passed the same way as arguments. Passing a bare 0 as variadic
pointer argument is likely to "work" (meaning that the error isn't
caught until the code is run on a platform where it fails).
--
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 14:29 -0700 |
| Message-ID | <5b2b7194-1ae5-49bd-aafa-197f58bd16f8@googlegroups.com> |
| In reply to | #112611 |
On Monday, June 19, 2017 at 2:08:40 PM UTC-5, Keith Thompson wrote: > David Brown writes: > > On 19/06/17 14:05, bartc wrote: > [...] > >> (a,b,0) can't be an integer constant expression, even if a and b are > >> constants, because the language considers that nonsensical. > > (a,b,0) isn't an integer constant expression because the language says > it isn't. The standard expresses no opinion on how sensible it would > be. (I wouldn't have any particular problem if the language permitted > comma operators in constant expressions, but forbidding them isn't a > problem either.) The Standard N1570 6.6p10 says "An implementation may accept other forms of constant expressions." While the rest of the Standard may specify that an implementation would be under no *obligation* to accept "(a,b,0)" as an integer constant expression, 6.6p10 would suggest to me that such an expression would be an integer constant expression on any implementation that, for whatever reason, chooses to regard it as such. N1570 6.3.2.3p3 says that an integer constant expression with value zero is a null-pointer constant. I see no reason that, combined with the latitude given in 6.6p10, would not imply that an implementation may silently allow any integer expression *whose value is always zero* to be coerced to a pointer type, without regard for whether the Standard would *require* it to recognize that value as constant.
[toc] | [prev] | [next] | [standalone]
Page 5 of 6 — ← Prev page 1 2 3 4 [5] 6 Next page →
Back to top | Article view | comp.lang.c
csiph-web