compare a large number of variables

D

Dietmar Schindler

Tim said:
Let's explore that. Characters are things like a, b, c, .... A
multibyte character is a sequence of bytes, ie a sequence of
memory locations. The set of characters is of some fixed size;
there are only so many of them. The set of (sequences of) memory
locations is of potentially unbounded size; certainly there can
be more memory locations than there are characters. If the set
of characters is smaller than the set of memory locations, how
can the set of memory locations be a subset of the set of
characters? If the set of memory locations is not a subset of
the set of characters, how can a memory location be a character?
A sequence of memory locations can represent characters, but they
are not themselves characters.

When you wrote "A multibyte character is a sequence of bytes", you
omitted an important qualification. 3.7.2 defines "multibyte character"
as "sequence of one or more bytes representing a member of the extended
character set ...". Sequences of bytes not representing a member of the
character set are not multibyte characters. Therefore, I can't follow
your reasoning at this point.
Similarly, the bit patterns in an eight-bit byte can represent
the numbers from zero to 255. We don't mean that a memory
location IS a number; a memory location -- or lots of different
memory locations -- can REPRESENT a number by having a certain
bit pattern stored in it (or them). There are only 256 numbers
between 0 and 255, but there are a lot more than 256 memory
locations -- there aren't enough numbers to go around so that
every memory location is a number. Or do you mean to say two
distinct memory locations can be the same, because they are
both (for example) the number 5?.

I think you're using "is" in the sense of "can stand in for".
And in that sense, I think I would agree with you -- a sequence
of memory locations (and the bit patterns stored therein) can
stand in for a character. But in technical writing the word "is"
is normally used in a different sense: if an X is a Y, then
the set of X's is a subset of the set of Y's. That sense of "is"
doesn't fit with what your statement about multibyte characters
implies.

Actually, I think it fits quite well; if I expand the statement "a
multibyte character is a character", I get "the set of sequences of one
or more bytes representing a member of the extended character set is a
subset of the set of members of a set of elements used for the
organization, control, or representation of data". I admit this could
probably be expressed less complicated, but I consider it to be correct.
Yes, I suspect the thread has lasted as long as it has because
your understanding of language and logic differs from that of
some other readers (mine in particular, but also some others).


Here's an example. We store the bit pattern 1000000, with a
value of 0 (on a signed magnitude implementation), into an
eight-bit byte. Subsequent reads of the object alternately
return 00000000, 10000000, 00000000, ..., all of which still have
the value 0. Is this behavior allowed by the statement that "an
object retains its last-stored value"?

I guess it's allowed when the contents of the byte are interpreted as
having a signed type and it's disallowed otherwise. But, I'm sorry, I
don't see the relevance of this example.
Second example:

int n;
unsigned char *p = (void*) &n;
p[0] = 0, p[1] = 1, p[2] = 2, p[3] = 3;

What is the last-stored value (in the sense of 3.17) of the
object n? Suppose the value (in the sense of 3.17) of n is
0x00010203; how could this value have been stored, since
no expression in the running program yields that value?

The answer to your first question here is implementation-defined or
undefined, of course. I hope you don't think I dismiss the second one
too thoughtlessly (I really thought quite some time over it), but the
answer is provided by the code snippet above, and again, I don't see why
this example should force anyone to believe that 3.17 could not apply to
the meaning of value in "last-stored value".
The statements you give support my assertion that the term
"value" is used with different senses in different places in
the Standard. What do you think "value" means in the
statements you quote, since it can't mean the same thing as the
definition in 3.17 p1?

In my opinion, in these statements [snipped to one representative]

"An object exists, has a constant address,25) and retains its
last-stored value throughout its lifetime."

the meaning of "value" is not at all different from its definition in
3.17. When I insert the definition into the statements, I get
[snipped to one representative]

"An object exists, has a constant address,25) and retains its
last-stored precise meaning of the contents of the object when
interpreted as having its specific type throughout its lifetime."

This may sound a little clumsy, but it is not illogical, is it?

Part of my problem with your reformulation is that I don't know
what the revised wording is meant to say. What is it that's
being stored? Is it a meaning, or a bit pattern? Let's look at
a slightly different wording:

"An object exists, has a constant address,25) and retains the
precise meaning of its last-stored contents of the object when
interpreted as having its specific type throughout its lifetime."

Does your statement mean the same thing as the rewording, or does
it mean something different? The rewording makes it clear that
what is being stored is "contents" rather than "meaning". A
"value" under 3.17 is a "meaning", so a 3.17-value is not what's
being stored (if the rewording is accurate). So which is it? Is
the statement about retaining the last-stored value inconsistent
with the 3.17 notion of value, or do you mean something different
by your statement than my proposed rewording? If the latter, then
what rewording would you propose?

It appears to me that although your rewording changes what is being
stored from "meaning" to "contents", what is retained ("meaning")
remains the same, and so the observable behaviour of a program would
remain the same, making the two versions of the statement functionally
equivalent.

And remember, you answered my question
that way:
Can't in C. Even functions like memcpy() act on "arrays
of character type and other objects treated as arrays of
character type" (7.21.1 p1).

So, we can't store anything without "meaning", i. e. type.
The statement about retaining the last-stored value is, in my opinion,
as well as all other statements in the standard, not inconsistent with
the 3.17 notion of value.
I wouldn't say I find your revised definitions illogical,
but they do seem (at least to me) nonsensical.

... I've tried to divine what
it is you've been trying to say, and some of that is expressed
above (how I think you mean "is", for example). So let's see if
I can articulate what I think is the Standard is trying to say.
Disclaimer: very off-the-cuff remarks follow.

The word "value" is used in several senses in the Standard.
The definition given in 3.17 uses "value" in the sense of
how we are to interpret the contents of an object, when
interpreted in a particular context (namely, as what type).

Many places in the Standard use "value" not in the sense of 3.17,
but the sense of "raw bit pattern". Thus, when we say that an
object retains its last-stored "value", this wording is meant
to say that an object retains the last bit pattern stored into
that object. Similarly, we say a write access modifies an
object even if the raw bit pattern being stored matches the
bit pattern already in the object.

There is some confusion between the two senses, and that
confusion has prompted some esoteric discussion in the comp.*.c
newsgroups. For example, suppose a particular address is stored
in a pointer variable, and then the memory at that address is
deallocated (by calling free(), for example). Is the bit pattern
that was stored in the pointer allowed to change? I remember
there being discussion at some point on this question, although I
don't remember the outcome. However, part of what prompted the
discussion in the first place -- and what made it difficult -- is
the confusion over which sense of "value" is meant in statements
like "an object retains its last-stored value". If "value" means
"raw bit pattern" you reach one conclusion, and if "value" means
value-ala'-3.17 you (can) reach another. Some of the debate
centered around this confusion, although I don't remember if it
was ever explicitly identified.

Note that I'm not saying that one sense is the true sense and the
other sense is wrong; there is some ambiguity in the Standard
itself, and that ambiguity deserves (IMO) a DR (which hopefully
would result in revised and improved wording, but let's not get
into that right now). But -- and here is the important thing --
many places in the Standard where "value" is used are best read
as though "value" meant "raw bit pattern". And that sense of
value is definitely different than "value" as defined in 3.17.

Does that all make sense?

I would be exaggerating here if I claimed that all made sense to me, but
it certainly did to some extent, and I understand your position better
now.

Unfortunately (or fortunatly, as it may also be perceived) I'll not be
able to continue this interesting (at least for me, maybe not so for
others) discussion for the next two weeks, because I'll be on vacation.
So long!
 
T

Tim Rentsch

Dietmar Schindler said:
Tim Rentsch wrote: [snip]
Note that my position is that undefined behavior is possible
even when two's complement representation is used. Two's
complement doesn't have a representation for negative zero,
so it isn't covered by the paragraph cited above. Even so,
bitwise operators on signed types that are represented using
two's complement may still result in undefined behavior.

Yes, however your wording "seems like bitwise operators on negative
operands can result in undefined behavior at any time" seems somewhat
exaggerated to me. With two's complement representation, I find exactly
one possibility for undefined behavior, and that's in

6.2.6.2 Integer types
2 ...
Which of these applies is implementation-defined, as is whether the
value with sign bit 1 and all value bits zero ... is a trap
representation or a normal value.

The exclusion of other possibilities of undefined behavior of bitwise
operators when two's complement representation is used is suggested, as I
understand it, by footnotes 44 and 45, which say "no arithmetic operation
on valid values can generate a trap representation other than as part of
an exceptional condition such as an overflow."

Yes, but here's the rub. If the bit pattern produced by a
bitwise operator corresponds to a trap representation for
the type in question, then it does not correspond to a value
for that type. This means the result is "not in the range
of representable values for its type", which makes it an
exceptional condition. So the comment in the footnotes
isn't as limiting as it might appear to be.

You're right that quoted remark "[it] seems like bitwise
operators on negative operands can result in undefined
behavior at any time" isn't literally exactly accurate. But
it's only a slight exaggeration. If the operands are of
type 'int', for example, I believe the integers 0, INT_MIN
and INT_MAX are required to be actual values. However, I
haven't found any language anywhere in the Standard that
would disallow every other int bit pattern from being a trap
representation.

Because the Standard places almost no restrictions on which
representations can be trap representations, I think it is
true that bitwise operators on negative operands can result
in undefined behavior at ALMOST any time. They won't on
most implementations of course. But on the famous
DeathStation 9000 - watch out!
 
T

Tim Rentsch

Since the standard assigns no special meaning to the term "pointer
constant", we're supposed to use ordinary rules of english usage to
interpret it. In the constext of the C standard, it has a meaning that
seems clear, obvious, and unambiguous to me (YMMV): a constant
expression with pointer type. In other words, it's essentially
synonymous with what the standard calls an "address constant". If it
weren't for the fact that the standard does provide a definition of
"null pointer constant", the obvious (to me) interpretation would be "a
constant expression with a pointer type and a null value"; which is NOT
how the standard defines it.

I'll chime in here, since it was my comment that started
this subthread between Keith Thompson and myself.

It's indeed true (which I didn't realize in my earlier
postings) that 6.6 talks about "address constants" in a
couple of paragraphs, especially paragraph 9 which gives
the definition for the term.

Reading through those paragraphs, I have to admit that it
seems like the authors thought of the phrase "null pointer
constant" as "(null pointer) constant" rather than "null
(pointer constant)". So Keith's (and Richard's) view is
more in line with how the people who wrote the phrase in the
first place seem to think of it.

Personally, I still think "null (pointer constant)" makes
sense and is more in line with the rules of regular English
usage. But I acknowledge that, if one were making an
argument, the "(null pointer) constant" view is more likely
to win the debate.
 
D

Douglas A. Gwyn

Tim said:
Reading through those paragraphs, I have to admit that it
seems like the authors thought of the phrase "null pointer
constant" as "(null pointer) constant" rather than "null
(pointer constant)". So Keith's (and Richard's) view is
more in line with how the people who wrote the phrase in the
first place seem to think of it.

No, it's a "null pointer constant", a technical term unto
itself. In contexts where a n.p.c. is allowed, one has to
refer to the syntactic definition to check if a n.p.c. is
in fact used. The logical tightrope is due to the great
*in*advisability of declaring anywhere that "0" (without
the quotation marks) *is* a n.p.c. It *can* be a n.p.c,
in certain contexts, but it isn't *always* a n.p.c.

Technical terms in the standard are not meant to be parsed
into English components and analyzed on that basis.
 
K

Keith Thompson

Douglas A. Gwyn said:
No, it's a "null pointer constant", a technical term unto
itself.
Ok.

In contexts where a n.p.c. is allowed, one has to
refer to the syntactic definition to check if a n.p.c. is
in fact used. The logical tightrope is due to the great
*in*advisability of declaring anywhere that "0" (without
the quotation marks) *is* a n.p.c. It *can* be a n.p.c,
in certain contexts, but it isn't *always* a n.p.c.

But that's not what the standard says. C99 6.3.2.3p3 says:

An integer constant expression with the value 0, or such an
expression cast to type void *, is called a _null pointer
constant_. If a null pointer constant is converted to a pointer
type, the resulting pointer, called a _null pointer_, is
guaranteed to compare unequal to a pointer to any object or
function.

It says that 0 is a null pointer constant, and describes what happens
*if* it's converted to a pointer type.

How are we to infer that in
int n = 0;
or even
0;
the 0 is not a null pointer constant, when the definition of the term
clearly states that it is? (It's an "integer constant expression with
the value 0").
Technical terms in the standard are not meant to be parsed
into English components and analyzed on that basis.

Agreed. Ideally the technical terms should be chosen so they make
sense as English phrases (and I have no complaints about "null pointer
constant" in that regard), but that's a secondary issue.

Are we to infer from the presence of the word "pointer" in the phrase
"null pointer constant" that a 0 appearing in a non-pointer context is
*not* a null pointer constant? Should we parse the term into English
components or shouldn't we?

Please note that I'm not saying that there's any problem with the 0 in
"int n = 0;" being a null pointer constant. Since it's not converted
to a pointer type, this is harmless and ignorable. 0 is many things:
an integer constant, an octal constant, a constant, a constant
expression, and so forth -- and it can be used in contexts where such
things are not specifically required.
 
T

Tim Rentsch

Douglas A. Gwyn said:
No, it's a "null pointer constant", a technical term unto
itself.

The two statements aren't inconsistent. I understand that
technical terms as used in the Standard are meant to be
taken as atomic units. My comment however is orthogonal
to that.

In contexts where a n.p.c. is allowed, one has to
refer to the syntactic definition to check if a n.p.c. is
in fact used. The logical tightrope is due to the great
*in*advisability of declaring anywhere that "0" (without
the quotation marks) *is* a n.p.c. It *can* be a n.p.c,
in certain contexts, but it isn't *always* a n.p.c.

What I think you mean is that expressions like '0' aren't
always used as null pointer constants. Or, to say that
another way, they may be null pointer constants, but that
they are null pointer constants has no logical consequences.

Technical terms in the standard are not meant to be parsed
into English components and analyzed on that basis.

Yes, I said almost exactly that recently to support a
statement that the term "indeterminate value" doesn't
necessarily imply that something is a "value".
 
D

Douglas A. Gwyn

Keith said:
How are we to infer that in
int n = 0;
the 0 is not a null pointer constant, ...

In that context it is irrelevant whether or not it "is" a n.p.c.
The only time it matters is when there is a *requirement* (maybe
one of several alternatives allowed in some context), in which
case one has to check whether the definition is met.

I think in an earlier version/draft of the standard we used
different wording, but the intent has always been the same.

We wouldn't have this issue at all if C had a reserved
keyword, "nil" or "NULL" or whatever, that had to be used
whenever one wished to denote a n.p.c. Designers of new
languages should take that approach.
 
K

Keith Thompson

Douglas A. Gwyn said:
In that context it is irrelevant whether or not it "is" a n.p.c.
The only time it matters is when there is a *requirement* (maybe
one of several alternatives allowed in some context), in which
case one has to check whether the definition is met.

I agree, but that doesn't answer my question.

Doug, a week or so ago it seemed to matter a great deal to you whether
0 is a null pointer constant in that particular context. Here's what
you wrote then:

] No, it's a "null pointer constant", a technical term unto
] itself. In contexts where a n.p.c. is allowed, one has to
] refer to the syntactic definition to check if a n.p.c. is
] in fact used. The logical tightrope is due to the great
] *in*advisability of declaring anywhere that "0" (without
] the quotation marks) *is* a n.p.c. It *can* be a n.p.c,
] in certain contexts, but it isn't *always* a n.p.c.
]
] Technical terms in the standard are not meant to be parsed
] into English components and analyzed on that basis.

I'm not claiming that the NPC-ness of 0 in a non-pointer context is of
any great significance. It's just an interesting little detail of the
language that most people probably aren't aware of, like the fact that
0 is an octal constant -- and I don't see anybody arguing that 0 is an
octal constant only if it appears in a context that requires an octal
constant. (That's partly because there are no such contexts, of
course.)

The standard clearly says that 0 is a null pointer constant. There is
no indication that it's a null pointer constant only in certain
contexts. You have argued forcefully that 0 should *not* be
considered a null pointer constant in certain contexts, in apparent
contradiction both to the standard and to your own statement that
"Technical terms in the standard are not meant to be parsed into
English components and analyzed on that basis".

I agree that it doesn't matter much that 0 in "int n = 0;" is a null
pointer constant -- but since you claim that it isn't, I'd like to
hear your justification for that claim.
I think in an earlier version/draft of the standard we used
different wording, but the intent has always been the same.

And what exactly is that intent? We can only go by what the standard
actually says, and perhaps by what members of the Committee tell us
about the intent. If the wording seems to conflict with the intent,
and if the actual wording doesn't create any problems, I think we have
to go by the actual wording.

If a future version of the standard stated that a null pointer
constant can only appear in a pointer context (a term that would have
to be defined), that would be fine with me, perhaps even an
improvement. But that's not what the standard says.
We wouldn't have this issue at all if C had a reserved
keyword, "nil" or "NULL" or whatever, that had to be used
whenever one wished to denote a n.p.c. Designers of new
languages should take that approach.

I agree completely. Now will you please answer my question?

The question itself is not important, but if there is a real reason to
think that the 0 in "int n = 0;" is *not* a null pointer constant,
then it means I have a serious misunderstanding of the standard, and
that's important (at least to me).
 
N

Niklas Matthies

If a future version of the standard stated that a null pointer
constant can only appear in a pointer context

....then this would disallow 0 in non-pointer contexts. Bad idea. ;)

-- Niklas Matthies
 
K

Keith Thompson

Niklas Matthies said:
...then this would disallow 0 in non-pointer contexts. Bad idea. ;)

No, just a mediocre idea expressed badly. What I meant was that the
definition of "null pointer constant" would be left as it is, *except*
that something that meets the current definition is considered to
be a null pointer constant only if it appears in a pointer context.
So "int n = 0;" would still be legal, but the 0 wouldn't be a null
pointer constant. (The concept of "pointer context" would have to
be defined.)

If worded carefully, such a change shouldn't affect any implementation
or program, just the way we talk about them.

I'm not advocating such a change, just saying that I wouldn't object
to it. The fact that 0 in the above is a null pointer constant (or,
if Doug is right and I'm missing something, the fact that it isn't)
causes no harm other than a bit of confusion.
 
D

Douglas A. Gwyn

Keith said:
... It's just an interesting little detail of the
language that most people probably aren't aware of, like the fact that
0 is an octal constant ...

Also (at least at one point) preprocessing number syntax
supported more constructs than were truly intended, but
since it was benign (the unwanted stuff would be caught
at a later stage of translation) we opted for the
simpler description.

My concern was that this thread seemed to be starting to
attribute more to the notion of n.p.c. than was ever
intended. While an unadorned "0" might be *called* a
n.p.c. (as the spec says) in a non-pointer context, it
is inappropriate to call it a n.p.c. in such a context,
because it is simply not a relevant attribute (in that
context). If you pedantically insist on doing the
contrary, you add to confusion about the concept.
 
D

Douglas A. Gwyn

Keith said:
If worded carefully, such a change shouldn't affect any implementation
or program, just the way we talk about them.

We considered how to express the concept and as a compromise
settled on the one you see in the spec. As I noted in a
separate posting, it's not the only place where we found
that a perfectly precise specification would be far more
complex than an approximate specification that covers
everything that matters but also benignly includes a few
other things that we would have preferred not to bundle
together. Most such instances arose from having to
conform to the historical design and evolution of the C
language, and could be avoided in an ab initio PL design.
 
K

Keith Thompson

Douglas A. Gwyn said:
Also (at least at one point) preprocessing number syntax
supported more constructs than were truly intended, but
since it was benign (the unwanted stuff would be caught
at a later stage of translation) we opted for the
simpler description.

My concern was that this thread seemed to be starting to
attribute more to the notion of n.p.c. than was ever
intended. While an unadorned "0" might be *called* a
n.p.c. (as the spec says) in a non-pointer context, it
is inappropriate to call it a n.p.c. in such a context,
because it is simply not a relevant attribute (in that
context). If you pedantically insist on doing the
contrary, you add to confusion about the concept.

I was merely attributing to the notion of n.p.c. exactly what the
standard attributes to it. I've acknowedged numerous times that the
question of whether an unadorned 0 is a null pointer constant isn't
very important. I raised the issue (this time) simply because *you*
insisted that it isn't, whereas the standard clearly says it is.

I believe my position is perfectly clear. 0 is a null pointer
constant. If it's converted to a pointer type, this fact is relevant.
If it's not converted to a pointer type, it's not being *used* as a
null pointer constant, but it still meets the definition, just as 0 is
a constant expression even when it's used in a context that doesn't
require one.

I'm not trying to create confusion; I'm trying to reduce the confusion
that's already there.

So your response to my question:

is "No"?
 
D

Douglas A. Gwyn

Keith said:
So your response to my question:
is "No"?

I try not to respond to cheap debating ploys such as making
the other guy answer a question that he might not think is
well posed or relevant. If something I have said isn't
clear enough, you can ask questions about it and if they
seem to be well-intentioned I'll probably respond.

The basic issue with a bare statement like "0 ... is a null
pointer constant" is that the use of "is" implies identity,
but actually 0 is several things, including an octal constant
as I think was mentioned elsewhere in this thread. The
n.p.c.ness is irrelevant and thus epistemologically
inappropriate to be considering in contexts where pointers
aren't involved. I tried to explain why we didn't say "0 ...
is a null pointer context in the following contexts...",
which would fit your model of definition. Basically it is
too hard to get it precisely right, and the looser approach
still has the right technical properties given the way that
the requirement for n.p.c.ness in some contexts is phrased
elsewhere in the standard.
 
K

Keith Thompson

Douglas A. Gwyn said:
I try not to respond to cheap debating ploys such as making
the other guy answer a question that he might not think is
well posed or relevant. If something I have said isn't
clear enough, you can ask questions about it and if they
seem to be well-intentioned I'll probably respond.

It was not a cheap debating ploy. I honestly don't know why you think
it was.
The basic issue with a bare statement like "0 ... is a null
pointer constant" is that the use of "is" implies identity,
but actually 0 is several things, including an octal constant
as I think was mentioned elsewhere in this thread.

No, it does not imply identity. If 0 is a null pointer constant, that
does not in any way imply that it's not *also* an octal constant, an
integer constant, a constant, a constant expression, etc. I believe
I've made that extremely clear.
The
n.p.c.ness is irrelevant and thus epistemologically
inappropriate to be considering in contexts where pointers
aren't involved.

Why? I acknowledge that it's not a very important point -- but *you*
are the one who seems to think it's terribly important that 0 in a
non-pointer context should *not* be considered a null pointer
constant. I am trying to understand your point.
I tried to explain why we didn't say "0 ...
is a null pointer context in the following contexts...",
which would fit your model of definition. Basically it is
too hard to get it precisely right, and the looser approach
still has the right technical properties given the way that
the requirement for n.p.c.ness in some contexts is phrased
elsewhere in the standard.

This has nothing to do with my "model of definition" (our earlier
dispute about whether definitions need to be exhaustive). I actually
don't have a problem with this aspect of the current definition of
"null pointer constant".

Once again:

Given the definition in C99 6.3.2.3p3 (which I find sufficiently
clear), and given something like:
int n = 0;
the 0 is a null pointer constant. The context doesn't *require* a
null pointer constant; nor does it require an octal constant, an
integer constant, a constant, or a constant expression. Nevertheless,
it is simultaneously a null pointer constant; nor does it require an
octal constant, an integer constant, a constant, and a constant
expression.

Is this correct? I'm not asking whether it's important or relevant,
I'm asking whether it's correct.

I do not consider this to be a flaw in the definition of "null pointer
constant". I can imagine a definition that would exclude this case,
but it would have to be more complex, and I think the current
definition is a good tradeoff.

All I've been trying to do here is reconcile what the standard says
(0 is a null pointer constant) with what you have written in this
thread:

] The logical tightrope is due to the great *in*advisability of
] declaring anywhere that "0" (without the quotation marks) *is* a
] n.p.c. It *can* be a n.p.c, in certain contexts, but it isn't
] *always* a n.p.c.

The only consistent interpretation I can think of is that 0 is always
a null pointer constant, but that it's very important for us not to
admit it in certain contexts. Is that what you mean?

My quarrel is not with the standard, it's with *your* statements.
 
K

Keith Thompson

Keith Thompson said:
Once again:

Given the definition in C99 6.3.2.3p3 (which I find sufficiently
clear), and given something like:
int n = 0;
the 0 is a null pointer constant. The context doesn't *require* a
null pointer constant; nor does it require an octal constant, an
integer constant, a constant, or a constant expression. Nevertheless,
it is simultaneously a null pointer constant; nor does it require an
octal constant, an integer constant, a constant, and a constant
expression.

Whoops, editing error. What I meant to write was:

Given the definition in C99 6.3.2.3p3 (which I find sufficiently
clear), and given something like:
int n = 0;
the 0 is a null pointer constant. The context doesn't *require* a
null pointer constant; nor does it require an octal constant, an
integer constant, a constant, or a constant expression. Nevertheless,
it is simultaneously a null pointer constant, an octal constant, an
integer constant, a constant, and a constant expression.
 
C

Charlie Gordon

Keith Thompson said:
Whoops, editing error. What I meant to write was:

Given the definition in C99 6.3.2.3p3 (which I find sufficiently
clear), and given something like:
int n = 0;
the 0 is a null pointer constant. The context doesn't *require* a
null pointer constant; nor does it require an octal constant, an
integer constant, a constant, or a constant expression. Nevertheless,
it is simultaneously a null pointer constant, an octal constant, an
integer constant, a constant, and a constant expression.

I must voice my disagreement :

0 is only a null pointer constant as a last resort. Context does matter!
Here is a simple infamous example to illustrate this sorry fact :

printf("%p", 0);

As we all know, this code in incorrect, and it will fail on architectures where
sizeof(void*) > sizeof(int)

The same is sadly true of

printf("%p", NULL);

if NULL is defined as 0 as is required for C++ and accepted for C.
 
K

Keith Thompson

Charlie Gordon said:
I must voice my disagreement :

0 is only a null pointer constant as a last resort. Context does matter!
Here is a simple infamous example to illustrate this sorry fact :

printf("%p", 0);

As we all know, this code in incorrect, and it will fail on
architectures where
sizeof(void*) > sizeof(int)

The same is sadly true of

printf("%p", NULL);

if NULL is defined as 0 as is required for C++ and accepted for C.

Of course. It will also fail on architectures where a null pointer
(specifically a null pointer of type void*) has a representation other
than all-bits-zero. But it doesn't fail because 0 isn't a null
pointer constant; it fails because it's not converted to a pointer
type.

Again, here's C99 6.3.2.3p3:

An integer constant expression with the value 0, or such an
expression cast to type void *, is called a _null pointer
constant_. If a null pointer constant is converted to a pointer
type, the resulting pointer, called a _null pointer_, is
guaranteed to compare unequal to a pointer to any object or
function.

According to this, the 0 in printf("%p", 0) is a null pointer constant
(which is a source code construct), but because it's not converted to
a pointer type, it doesn't yield a null pointer at run time.

The fact that this 0 is a null pointer constant happens to be a null
pointer constant turns out not to be useful, just as it's not useful
to know that it's an octal constant. That doesn't make it untrue.

I see nothing in the definition of "null pointer constant" that
implies that the definition depends on the context in which it
appears. What are you seeing that I'm not?

There are many null pointer constants that aren't *used* as null
pointer constants -- and that's ok.
 
R

Roland Illig

Charlie said:
printf("%p", 0);

As we all know, this code in incorrect, and it will fail on architectures where
sizeof(void*) > sizeof(int)

Not quite. If the argument passing scheme doesn't care about the size,
for example by using registers for both types, there's no difference. On
NetBSD, this is said to work:

http://mail-index.netbsd.org/tech-userlevel/2005/04/13/0000.html
http://mail-index.netbsd.org/tech-userlevel/2005/04/13/0001.html
http://mail-index.netbsd.org/tech-userlevel/2005/04/13/0002.html
http://mail-index.netbsd.org/tech-userlevel/2005/04/13/0003.html

Nevertheless, the code is not portable and should be avoided.

Roland
 
K

Keith Thompson

Roland Illig said:

Even assuming both types are passed in the *same* register, the code
can fail if a null pointer isn't represented as all-bits-zero. There
may be other ways it can fail that I can't think of off the top of my
head.
Nevertheless, the code is not portable and should be avoided.

Yup. In fact, it invokes undefined behavior, with all that implies.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top