can you tell that y the code is work like that

T

Tim Rentsch

Default User said:
My two data points are the VC++ 6.0 and gcc 3.3.1 on Solaris, which
both give an all-bits-zero null pointer.

Note that this doesn't have anything to do with the standard language
at all. It's been my impression from previous discussion that some non
0 null pointers exist, but that they were in the minority.

We're talking about two different things. My comment was about
the definition of the NULL macro, whether it is, eg,

#define NULL 0

or, eg,

#define NULL (void*)0

Your comment is about the representation - eg, "all-bits-zero" -
of a null pointer (whether or not it comes from NULL). I wasn't
making any representations about the representation of a null
pointer.
 
N

Nils Weller

Default User said:
We're talking about two different things. My comment was about
the definition of the NULL macro, whether it is, eg,

#define NULL 0

or, eg,

#define NULL (void*)0


I'm thinking the latter would be better phrased as

((void *)0)

.... because omission of the parentheses causes NULL not to group in
expressions as though it were a single identifier, thus violating C90+
TC1 and C99. The text that says this is in subclause 7.1.2 and
identically worded in both standards:

Any definition of an object-like macro described in this clause
shall expand to code that is fully protected by parentheses where
necessary, so that it groups in an arbitrary expression as if it
were a single identifier.

(This was added to C90 in response to Defect Report 43:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_043.html

and has been discussed in comp.std.c before:

http://groups.google.com/group/comp...9601a455435be?q=sizeof-null+comp.std.c&hl=en&)
 
D

Default User

Tim Rentsch wrote:

We're talking about two different things. My comment was about
the definition of the NULL macro, whether it is, eg,

#define NULL 0

or, eg,

#define NULL (void*)0

Your comment is about the representation - eg, "all-bits-zero" -
of a null pointer (whether or not it comes from NULL). I wasn't
making any representations about the representation of a null
pointer.


I see. Most of the headers I've looked at tend to either define it as 0
or use #ifdefs to give 0 for C++ or (void *)0 for C.



Brian
 
T

Tim Rentsch

Nils Weller said:
Default User said:
We're talking about two different things. My comment was about
the definition of the NULL macro, whether it is, eg,

#define NULL 0

or, eg,

#define NULL (void*)0


I'm thinking the latter would be better phrased as

((void *)0)

... because omission of the parentheses causes NULL not to group in
expressions as though it were a single identifier, thus violating C90+
TC1 and C99. The text that says this is in subclause 7.1.2 and
identically worded in both standards:

Any definition of an object-like macro described in this clause
shall expand to code that is fully protected by parentheses where
necessary, so that it groups in an arbitrary expression as if it
were a single identifier.

It was just an example. Any definition that results in a
value other than integer 0 would serve the purpose of the
example. There are definitions of NULL that use (void*)0
rather than ((void*)0).

But to respond to the point, a system header file could
include a definition

#define NULL (void*)0

and the implementation still meet the requirements of
C90+TC1 and C99; that could be done by having the compiler
check whether a text sequence '(void*)0' arose as a result
of expanding NULL, and whether the definition came from the
system file, and if so treat the expansion as an atomic
unit. An implementation is allowed to do this sort of thing
for definitions in system header files. There's even an
argument that says it's better to do this, since the
Standard's definition of the term "null pointer constant"
comprises '(void*)0' but not '((void*)0)'; however, I'm not
trying to say that it's better, only that it's allowed and
can be conformant.
 
N

Nils Weller

Nils Weller said:
I'm thinking the latter would be better phrased as

((void *)0)

... because omission of the parentheses causes NULL not to group in
expressions as though it were a single identifier, thus violating C90+
TC1 and C99.
[...]
But to respond to the point, a system header file could
include a definition

#define NULL (void*)0

and the implementation still meet the requirements of
C90+TC1 and C99; that could be done by having the compiler
check whether a text sequence '(void*)0' arose as a result
of expanding NULL, and whether the definition came from the
system file, and if so treat the expansion as an atomic
unit. An implementation is allowed to do this sort of thing
for definitions in system header files. There's even an
argument that says it's better to do this, since the
Standard's definition of the term "null pointer constant"
comprises '(void*)0' but not '((void*)0)'; however, I'm not
trying to say that it's better, only that it's allowed and
can be conformant.

True, but your definition only works with this hypothetical
implementation that you speak of and violates the standards
if applied to most if not all typical, real-world
implementations today. So if we are after portability (which
I think most c.l.c. readers are), why not use the portable
definition in examples :)

(I don't mean to hijack and turn this thread into a debate
about this irrelevant detail; I just thought it would be
interesting to mention this.)
 
K

Keith Thompson

Tim Rentsch said:
But to respond to the point, a system header file could
include a definition

#define NULL (void*)0

and the implementation still meet the requirements of
C90+TC1 and C99; that could be done by having the compiler
check whether a text sequence '(void*)0' arose as a result
of expanding NULL, and whether the definition came from the
system file, and if so treat the expansion as an atomic
unit. An implementation is allowed to do this sort of thing
for definitions in system header files. There's even an
argument that says it's better to do this, since the
Standard's definition of the term "null pointer constant"
comprises '(void*)0' but not '((void*)0)'; however, I'm not
trying to say that it's better, only that it's allowed and
can be conformant.

If the implementation plays tricks like that, it's not very meaningful
to say that NULL is defined in any particular way. There might be
something in some file that looks like a macro definition, but it's
not really *the* definition of NULL.

I'm not convinced that such tricks are legal anyway. Can you cite a
clause of the standard that says they are?
 
S

Skarmander

Tim Rentsch wrote:
But to respond to the point, a system header file could
include a definition

#define NULL (void*)0

and the implementation still meet the requirements of
C90+TC1 and C99; that could be done by having the compiler
check whether a text sequence '(void*)0' arose as a result
of expanding NULL, and whether the definition came from the
system file, and if so treat the expansion as an atomic
unit. An implementation is allowed to do this sort of thing
for definitions in system header files. There's even an
argument that says it's better to do this, since the
Standard's definition of the term "null pointer constant"
comprises '(void*)0' but not '((void*)0)'; however, I'm not
trying to say that it's better, only that it's allowed and
can be conformant.

There's also a good argument for why this isn't such an attractive
approach, namely that it involves merging the preprocessor with the
compiler, or at least a good part of it. Design-wise, it makes sense to
keep them separated -- even if they're integrated in one program.

Actually, it's a tad worse, because it also means making the
preprocessor cope with "special" behaviour in system headers. Coping
with broken or weird headers to somehow squeeze compliance out of them
(assuming compiler and C library are separate) is already something of a
black art, so reducing transparency by shifting the behaviour into
binaries (rather than using scripts that fix (copies of) the headers)
isn't such a hot idea.

S.
 
T

Tim Rentsch

Nils Weller said:
Nils Weller said:
[...]
#define NULL (void*)0


I'm thinking the latter would be better phrased as

((void *)0)

... because omission of the parentheses causes NULL not to group in
expressions as though it were a single identifier, thus violating C90+
TC1 and C99.
[...]
But to respond to the point, a system header file could
include a definition

#define NULL (void*)0

and the implementation still meet the requirements of
C90+TC1 and C99; that could be done by having the compiler
check whether a text sequence '(void*)0' arose as a result
of expanding NULL, and whether the definition came from the
system file, and if so treat the expansion as an atomic
unit. An implementation is allowed to do this sort of thing
for definitions in system header files. There's even an
argument that says it's better to do this, since the
Standard's definition of the term "null pointer constant"
comprises '(void*)0' but not '((void*)0)'; however, I'm not
trying to say that it's better, only that it's allowed and
can be conformant.

True, but your definition only works with this hypothetical
implementation that you speak of and violates the standards
if applied to most if not all typical, real-world
implementations today. So if we are after portability (which
I think most c.l.c. readers are), why not use the portable
definition in examples :)

Portability?!?? I thought most posters in c.l.c were after
opportunities to show off their knowledge of ISO C minutiae.
Also it's important to have examples be right near the edge
of the envelope of what the Standard allows, so newbies can
learn from the ensuing debates. Aren't these rules covered
in the FAQ?

(ok, ok, just kidding!)
 
T

Tim Rentsch

Skarmander said:
Tim Rentsch wrote:


There's also a good argument for why this isn't such an attractive
approach, namely that it involves merging the preprocessor with the
compiler, or at least a good part of it. Design-wise, it makes sense to
keep them separated -- even if they're integrated in one program.

Oh, I never said the argument for using '(void*)0' without the outer
parentheses was a *good* argument; only that there is an argument.

Actually, it's a tad worse, because it also means making the
preprocessor cope with "special" behaviour in system headers. Coping
with broken or weird headers to somehow squeeze compliance out of them
(assuming compiler and C library are separate) is already something of a
black art, so reducing transparency by shifting the behaviour into
binaries (rather than using scripts that fix (copies of) the headers)
isn't such a hot idea.

Apparently my message has been read by some people as advocating
the #define line above as a good way to define NULL. I wasn't.
My point was only about what's allowed, not what's good.
 
T

Tim Rentsch

Keith Thompson said:
If the implementation plays tricks like that, it's not very meaningful
to say that NULL is defined in any particular way. There might be
something in some file that looks like a macro definition, but it's
not really *the* definition of NULL.

There is some merit in what you say. Depending on special purpose
processing like this makes it difficult to talk about program
elements with our usual vocabulary, because the meanings of the
words have gotten rather slippery.

However, I don't think it diminishes my basic point, which is that we
can't conclude a priori that the #define line above "can't work". For
example, suppose the system header file contained these lines:

#pragma object_macro NULL
...
#define NULL (void*)0

with the obvious meaning for the #pragma line. I think most
people wouldn't be especially bothered by an implementation
that defined NULL in this way; surprised perhaps, but not
especially bothered. Furthmore, in some sense this definition
reflects more directly what the Standard requires of NULL -
namely, that it is an object macro, and that it produces a null
pointer constant.

To restate my basic point: we can't conclude a priori that
a #define line

#define NULL (void*)0

has problems; it's allowed, and it can be conformant. And
I would now add: in ways that aren't too much of a stretch.


I'm not convinced that such tricks are legal anyway. Can you cite a
clause of the standard that says they are?

Basically 7.1.2, especially paragraph 1. System headers don't have
to be files in the ordinary sense, and the wording in the Standard
says that the "contents [of the header] are made available by
the #include preprocessing directive." The contents are "made
available", but there don't seem to be any restrictions on
how that's done, or what form the "contents" take. Also I think
it's fairly commonly accepted that an implementation is allowed
to treat system functions in special ways, eg, inline data movement
for 'memcpy()'; I guess this freedom is generally allowed under
the "as if" rule, which seems to apply equally to NULL as it does
to memcpy(), etc.
 
J

Jordan Abel

If the implementation plays tricks like that, it's not very
meaningful to say that NULL is defined in any particular way.
There might be something in some file that looks like a macro
definition, but it's not really *the* definition of NULL.

I'm not convinced that such tricks are legal anyway. Can you cite
a clause of the standard that says they are?

It's called the "as if" rule - I don't know where if anywhere it's
spelled out in the standard, but it's used pretty much everywhere -
a good explanation is in the rationale document section 2.1

standard header files aren't required to exist at all, either - the
compiler could just know what each one means
 
K

Keith Thompson

Tim Rentsch said:
There is some merit in what you say. Depending on special purpose
processing like this makes it difficult to talk about program
elements with our usual vocabulary, because the meanings of the
words have gotten rather slippery.

However, I don't think it diminishes my basic point, which is that we
can't conclude a priori that the #define line above "can't work". For
example, suppose the system header file contained these lines:

#pragma object_macro NULL
...
#define NULL (void*)0

with the obvious meaning for the #pragma line. I think most
people wouldn't be especially bothered by an implementation
that defined NULL in this way; surprised perhaps, but not
especially bothered. Furthmore, in some sense this definition
reflects more directly what the Standard requires of NULL -
namely, that it is an object macro, and that it produces a null
pointer constant.

Ok, I had forgotten about #pragma. An implementation can do just
about anything with that. A #pragma not followed by STDC "causes the
implementation to behave in an implementation-defined manner. The
behavior might cause translation to fail or cause the translator or
the resulting program to behave in a non-conforming manner."
To restate my basic point: we can't conclude a priori that
a #define line

#define NULL (void*)0

has problems; it's allowed, and it can be conformant. And
I would now add: in ways that aren't too much of a stretch.

Given that definition, without some kind of trickery, the following:
printf("sizeof NULL = %d\n", (int)sizeof NULL);
is a syntax error. A #pragma is the only thing I can think of that
avoids the problem.
I'm not convinced that such tricks are legal anyway. Can you cite a
clause of the standard that says they are?

Basically 7.1.2, especially paragraph 1. System headers don't have
to be files in the ordinary sense, and the wording in the Standard
says that the "contents [of the header] are made available by
the #include preprocessing directive." The contents are "made
available", but there don't seem to be any restrictions on
how that's done, or what form the "contents" take. Also I think
it's fairly commonly accepted that an implementation is allowed
to treat system functions in special ways, eg, inline data movement
for 'memcpy()'; I guess this freedom is generally allowed under
the "as if" rule, which seems to apply equally to NULL as it does
to memcpy(), etc.

Certainly the standard headers don't have to be files, but I tend to
think (i.e., I can't necessarily prove it) that making the contents
available implies that the contents are going to look and act like C
source -- or, more precisely, that including a standard header has the
same effect as including an actual file.

Here's what I'd do if I wanted a well-behaved NULL macro. (I
understand you're not advocating the trickery you describe, just
arguing that it's legal, so this isn't a refutation.)

enum { __null };
#define NULL __null

Any use of __null, and therefore of NULL, is equivalent to a literal
0, which is of course a valid null pointer constant. The compiler
could recognize uses of the __null literal and issue warnings
(non-required diagnostics) for any misuse, such as using it in a
non-pointer context. It could optionally warn about the use of any
null pointer constant other than __null in a pointer context. Unlike
NULL, the _null literal survives past the preprocessing phase, so
there's no need to do anything ugly across translation phases.
 
S

Skarmander

Tim said:
Apparently my message has been read by some people as advocating
the #define line above as a good way to define NULL. I wasn't.
My point was only about what's allowed, not what's good.

"There's even an argument that says it's better to do this". Come on,
that warrants a rebuttal. :)

I never claimed *you* thought it was a good idea, or that you were
advocating it. Doesn't mean counterarguments weren't in order. A great
many things are "allowed" that still need to be avoided.

S.
 
T

Tim Rentsch

Skarmander said:
"There's even an argument that says it's better to do this". Come on,
that warrants a rebuttal. :)

I never claimed *you* thought it was a good idea, or that you were
advocating it. Doesn't mean counterarguments weren't in order. A great
many things are "allowed" that still need to be avoided.

Does this mean you'd present a counterargument even if no one was
advocating the argument?
 
S

Skarmander

Tim said:
Does this mean you'd present a counterargument even if no one was
advocating the argument?

Yes. I just did, didn't I?

TR: "Here's an approach. I'm not saying it's a good approach, just that
it's allowed."
S: "And here's why it's not a good approach."

What's wrong with this? I'm protecting the innocent. :)

S.
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
I'm not convinced that such tricks are legal anyway. Can you cite a
clause of the standard that says they are?

Basically 7.1.2, especially paragraph 1. System headers don't have
to be files in the ordinary sense, and the wording in the Standard
says that the "contents [of the header] are made available by
the #include preprocessing directive." The contents are "made
available", but there don't seem to be any restrictions on
how that's done, or what form the "contents" take. Also I think
it's fairly commonly accepted that an implementation is allowed
to treat system functions in special ways, eg, inline data movement
for 'memcpy()'; I guess this freedom is generally allowed under
the "as if" rule, which seems to apply equally to NULL as it does
to memcpy(), etc.

Certainly the standard headers don't have to be files, but I tend to
think (i.e., I can't necessarily prove it) that making the contents
available implies that the contents are going to look and act like C
source -- or, more precisely, that including a standard header has the
same effect as including an actual file.

You may very well be right. Even if so, however, it's hard to
draw any conclusions based on that, because the contents of a
file could depend on implementation-dependent extensions, which
the implementation itself is allowed to make use of, especially
in system header files.

Here's what I'd do if I wanted a well-behaved NULL macro. (I
understand you're not advocating the trickery you describe, just
arguing that it's legal, so this isn't a refutation.)

enum { __null };
#define NULL __null

Any use of __null, and therefore of NULL, is equivalent to a literal
0, which is of course a valid null pointer constant. The compiler
could recognize uses of the __null literal and issue warnings
(non-required diagnostics) for any misuse, such as using it in a
non-pointer context. It could optionally warn about the use of any
null pointer constant other than __null in a pointer context. Unlike
NULL, the _null literal survives past the preprocessing phase, so
there's no need to do anything ugly across translation phases.

To my surprise (and at least mild astonishment) I discovered
that __null is already used by gnu C++ as a special kind of
built-in null pointer constant in C++ compilations. Indeed
NULL is defined using just the #define line as is written above
(under suitable #if guards) for this usage in C++. A google
search turned up something else interesting - a proposal for
C++ to add a keyword "nullptr" that would be the "officially
approved" null pointer constant. Here's a link, for anyone
who is interested:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1488.pdf

"Alas! he gets nothing by that."
 
T

Tim Rentsch

Skarmander said:
Tim Rentsch wrote: [snip]
Does this mean you'd present a counterargument even if no one was
advocating the argument?

Yes. I just did, didn't I?

TR: "Here's an approach. I'm not saying it's a good approach, just that
it's allowed."
S: "And here's why it's not a good approach."

What's wrong with this? I'm protecting the innocent. :)

Nothing wrong with offering a counterargument when no one is
advocating the argument. It's important however to take
that into account when framing the counterargument.

When there's an advocate, the counter-arguer can expect the
advocate to look for any holes in the counterargument. But
when there isn't, shortcomings in the counterargument are
less likely to get noticed.

In the absence of an advocate on the other side, the
counter-arguer should be equally zealous in exploring both
sides of an argument; in fact, probably a little more
zealous in exploring the side being argued against, to
protect against unconsciously favoring the side of the
counterargument.
 
S

Skarmander

Tim said:
Tim Rentsch wrote:
[snip]

Does this mean you'd present a counterargument even if no one was
advocating the argument?

Yes. I just did, didn't I?

TR: "Here's an approach. I'm not saying it's a good approach, just that
it's allowed."
S: "And here's why it's not a good approach."

What's wrong with this? I'm protecting the innocent. :)


Nothing wrong with offering a counterargument when no one is
advocating the argument. It's important however to take
that into account when framing the counterargument.

When there's an advocate, the counter-arguer can expect the
advocate to look for any holes in the counterargument. But
when there isn't, shortcomings in the counterargument are
less likely to get noticed.

In the absence of an advocate on the other side, the
counter-arguer should be equally zealous in exploring both
sides of an argument; in fact, probably a little more
zealous in exploring the side being argued against, to
protect against unconsciously favoring the side of the
counterargument.

Right. I'll keep that in mind next time, so I can... actually, I have no
idea what was wrong with my reply. I'm sorry for not producing the
thoroughly researched essay you were apparently expecting, but if it
makes you feel better, just think of me as the peanut gallery.

I saw clear reasons why the implementation you sketched would have
drawbacks. I presented these drawbacks. The end. I wasn't trying to
enroll in Debating 101. Had I been, I would have stated much more
forcefully that I am obviously right, using hollow rhetoric and
grandiose emotional appeals. :)

In any case, I sense a thread that's past the point of diminishing returns.

S.
 
T

Tim Rentsch

Skarmander said:
Tim Rentsch wrote: [snip]
Nothing wrong with offering a counterargument when no one is
advocating the argument. It's important however to take
that into account when framing the counterargument.

When there's an advocate, the counter-arguer can expect the
advocate to look for any holes in the counterargument. But
when there isn't, shortcomings in the counterargument are
less likely to get noticed.

In the absence of an advocate on the other side, the
counter-arguer should be equally zealous in exploring both
sides of an argument; in fact, probably a little more
zealous in exploring the side being argued against, to
protect against unconsciously favoring the side of the
counterargument.

Right. I'll keep that in mind next time, so I can... actually, I have no
idea what was wrong with my reply. I'm sorry for not producing the
thoroughly researched essay you were apparently expecting, but if it
makes you feel better, just think of me as the peanut gallery.

I wasn't meaning to complain; just making a suggestion.

I saw clear reasons why the implementation you sketched would have
drawbacks. I presented these drawbacks. The end. I wasn't trying to
enroll in Debating 101. Had I been, I would have stated much more
forcefully that I am obviously right, using hollow rhetoric and
grandiose emotional appeals. :)

Different people engage in argument for different reasons.
Some people engage in argument so they can win the debate.
Other people engage in argument to better understand what
is true. I tend to favor the latter.

The problem I had with the counterargument is that it seems
like it possible objections to it hadn't been explored. I
wasn't willing to "take up the challenge", as it were, so I
let it drop. But, I thought you might appreciate the feedback
that the counterargument you gave wasn't convincing, because
only one side was explored. Does that make sense?

In any case, I sense a thread that's past the point of diminishing returns.

Near there, for sure. Fortunately it's labelled OT now...
 

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,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top