By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,786 Members | 1,143 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,786 IT Pros & Developers. It's quick & easy.

can you tell that y the code is work like that

P: n/a
int *p=20;
printf("%d",*p);
printf("%d",p);

the above code prints the output as
somegarbage value //for *p(may be address
20 //for p
why can you explain
thanks for that

Nov 15 '05 #1
Share this Question
Share on Google+
38 Replies


P: n/a
venkatesh, le 21/10/2005, a écrit :
int *p=20;
printf("%d",*p);
printf("%d",p);

the above code prints the output as
somegarbage value //for *p(may be address
20 //for p
why can you explain
thanks for that


int dummy = 20;
int* p = &dummy;
printf("%d\n",*p);
printf("%p\n",p);

or

int* p = malloc(sizeof int);
*p = 20;
printf("%d\n",*p);
printf("%p\n",p);

--
Pierre Maurette
Nov 15 '05 #2

P: n/a
venkatesh <pv***********@gmail.com> wrote:
int *p=20;
Broken. What makes you suspect that 20 is an appropriate value for a
pointer to an integer?
printf("%d",*p);
Broken. What exactly do you think a pointer with the value 20 might
point to?
printf("%d",p);
Broken. The size of a pointer to an integer need not be equal to
sizeof(int).

printf( "%p", (void*)p );
why can you explain


Pure random chance, as far as the C standard is concerned.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 15 '05 #3

P: n/a
venkatesh a écrit :
int *p=20;


This is kinda nonsense. What to you think it meant ?

The portable way of initializing a pointer to an object are

- NULL
- The address of an object of the same type
- the value returned by malloc()
- the value returned by fopen() if the type is void* or FILE*
and similar cases.

But initialising a pointer with a plain integer is undefined by the
language. Actually, it may work on a specific platform. It's called an
implementation-dependent behaviour.

--
C is a sharp tool
Nov 15 '05 #4

P: n/a
yes,
exactly what you wrote means:
int* p;
p = 20;

Nov 15 '05 #5

P: n/a
vire wrote:
yes,
exactly what you wrote means:
int* p;
p = 20;


Please read my .sig.
Brian

--
Please quote enough of the previous message for context. To do so from
Google, click "show options" and use the Reply shown in the expanded
header.
Nov 15 '05 #6

P: n/a
Christopher Benson-Manica <at***@nospam.cyberspace.org> writes:
venkatesh <pv***********@gmail.com> wrote:
int *p=20;


Broken. What makes you suspect that 20 is an appropriate value for a
pointer to an integer?


What's surprising is that his compiler thought it was appropriate.

A compiler might allow assigning an integer value to a pointer as an
extension, but if the code is compiled in strict mode (might be called
"ansi" or "iso", depending on the compiler), the compiler is required
to issue a diagnostic.

[...]
printf("%d",p);


Broken. The size of a pointer to an integer need not be equal to
sizeof(int).


Size matters not. Using "%d" to print a pointer value invokes
undefined behavior (though it will often do what you expect anyway).
It can fail even if int and int* happen to have the same size.

The correct way to print an int* value is:

printf("%p", (void*)p);

Also, the original code, if it doesn't blow up, will probably print
the values adjacent to each other; you won't be able to tell where one
ends and the other begins. Rather than

int *p=20;
printf("%d",*p);
printf("%d",p);

you might try this:

int *p = (int*)20;
printf("*p = %d\n", *p);
printf("p = %p\n", (int*)p);

Of course this could still invoke undefined behavior, since (int*)20
is unlikely to be a valid address.

Here's a program that actually works:

#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int *p = malloc(sizeof *p);
if (p == NULL) {
printf("malloc failed\n");
}
else {
*p = 20;
printf("*p = %d\n", *p);
printf("p = %p\n", (void*)p);
}
return 0;
}

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #7

P: n/a
Keith Thompson <ks***@mib.org> wrote:
The correct way to print an int* value is: printf("%p", (void*)p);
(which I did mention, FWIW)
Of course this could still invoke undefined behavior, since (int*)20
is unlikely to be a valid address.


Is it not UB regardless, since 20 is not a value obtained from
malloc()?

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 15 '05 #8

P: n/a
Emmanuel Delahaye <em**********@noos.fr> writes:
venkatesh a écrit :
int *p=20;
This is kinda nonsense. What to you think it meant ?

The portable way of initializing a pointer to an object are

- NULL
- The address of an object of the same type
- the value returned by malloc()
- the value returned by fopen() if the type is void* or FILE*
and similar cases.


And 0 (or any 0-valued constant expression).

But initialising a pointer with a plain integer is undefined by the
language.


Unless the integer is 0.
Nov 15 '05 #9

P: n/a
Christopher Benson-Manica <at***@nospam.cyberspace.org> writes:
Keith Thompson <ks***@mib.org> wrote:
The correct way to print an int* value is:

printf("%p", (void*)p);


(which I did mention, FWIW)


Ok.
Of course this could still invoke undefined behavior, since (int*)20
is unlikely to be a valid address.


Is it not UB regardless, since 20 is not a value obtained from
malloc()?


Valid pointers don't have to be obtained from malloc().

The conversion itself yields an implementation-defined result:

An integer may be converted to any pointer type. Except as
previously specified, the result is implementation-defined, might
not be correctly aligned, might not point to an entity of the
referenced type, and might be a trap representation.

with a footnote:

The mapping functions for converting a pointer to an integer or an
integer to a pointer are intended to be consistent with the
addressing structure of the execution environment.

If the result happens to be an invalid pointer, dereferencing it
invokes undefined behavior. If the implementation happens to
guarantee that 20 is a valid address for an int, the behavior of
dereferencing (int*)20 is merely implementation-defined.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #10

P: n/a
Tim Rentsch a écrit :
The portable way of initializing a pointer to an object are

- NULL
<...> And 0 (or any 0-valued constant expression). Unless the integer is 0.


NULL was supposed to cover the case...

--
C is a sharp tool
Nov 15 '05 #11

P: n/a
Emmanuel Delahaye <em**********@noos.fr> writes:
Tim Rentsch a écrit :
The portable way of initializing a pointer to an object are

- NULL

<...>
And 0 (or any 0-valued constant expression).

Unless the integer is 0.


NULL was supposed to cover the case...


I guessed that might have been the intention; however,
NULL is not guaranteed to be 0, and typically in fact
it isn't.
Nov 15 '05 #12

P: n/a
On 2005-10-26, Tim Rentsch <tx*@alumnus.caltech.edu> wrote:
Emmanuel Delahaye <em**********@noos.fr> writes:
Tim Rentsch a écrit :
>>The portable way of initializing a pointer to an object are
>>
>>- NULL

<...>
> And 0 (or any 0-valued constant expression).

> Unless the integer is 0.


NULL was supposed to cover the case...


I guessed that might have been the intention; however,
NULL is not guaranteed to be 0, and typically in fact
it isn't.


It's not guaranteed to be all-bits-zero, but that's not what he claimed. It
might be ((void *)0) or something like that, but i very much doubt anyone has
it as ((void *)0xdeadbeef), especially given that NULL _is_ guaranteed to
become 0 when converted to an integer
Nov 15 '05 #13

P: n/a
Jordan Abel <jm****@purdue.edu> writes:
On 2005-10-26, Tim Rentsch <tx*@alumnus.caltech.edu> wrote:

[...]
I guessed that might have been the intention; however,
NULL is not guaranteed to be 0, and typically in fact
it isn't.


It's not guaranteed to be all-bits-zero, but that's not what he claimed. It
might be ((void *)0) or something like that, but i very much doubt anyone has
it as ((void *)0xdeadbeef), especially given that NULL _is_ guaranteed to
become 0 when converted to an integer


No, I don't believe it is.

If NULL is defined as 0, then of course it's already of type int. But
if NULL is defined as (void*)0, then it's an expression of type void*,
and there's no guarantee that converting it to int will yield the
value 0.

The only specific guarantee is that a null pointer constant converted
to a pointer type yields a null pointer, and that only applies at
compilation time.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #14

P: n/a
On 2005-10-26, Keith Thompson <ks***@mib.org> wrote:
Jordan Abel <jm****@purdue.edu> writes:
On 2005-10-26, Tim Rentsch <tx*@alumnus.caltech.edu> wrote: [...]
I guessed that might have been the intention; however,
NULL is not guaranteed to be 0, and typically in fact
it isn't.


It's not guaranteed to be all-bits-zero, but that's not what he claimed. It
might be ((void *)0) or something like that, but i very much doubt anyone has
it as ((void *)0xdeadbeef), especially given that NULL _is_ guaranteed to
become 0 when converted to an integer


No, I don't believe it is.

If NULL is defined as 0, then of course it's already of type int.
But if NULL is defined as (void*)0, then it's an expression of
type void*, and there's no guarantee that converting it to int
will yield the value 0.


I could have sworn that there was a guarantee that null pointers
(constant or otherwise) convert to zero

how does if(p) work, then? if(p != 0) can be explained by the 0
being converted to a null pointer, and !p is defined as 0==p but i
could have sworn the argument in a conditional had to be an integer
type
The only specific guarantee is that a null pointer constant
converted to a pointer type yields a null pointer, and that only
applies at compilation time.


actually, though i could find nothing supporting my belief about
conversions to integer, apparently (from my interpretation)
conversions from any null pointer to any pointer type [at least, any
that the original pointer type is allowed to be converted to - void
pointer and pointer types with 'less strict alignment'] yield a null
pointer - constant or otherwise. It doesn't actually say that, but
you can get as far as "will compare equal [with the original null
pointer]" from other statements, and it seems implied that any
pointer that will compare equal with a null pointer is a null
pointer.
Nov 15 '05 #15

P: n/a
Jordan Abel <jm****@purdue.edu> writes:
On 2005-10-26, Tim Rentsch <tx*@alumnus.caltech.edu> wrote:
Emmanuel Delahaye <em**********@noos.fr> writes:
Tim Rentsch a écrit :
>>The portable way of initializing a pointer to an object are
>>
>>- NULL
<...>
> And 0 (or any 0-valued constant expression).

> Unless the integer is 0.

NULL was supposed to cover the case...


I guessed that might have been the intention; however,
NULL is not guaranteed to be 0, and typically in fact
it isn't.


It's not guaranteed to be all-bits-zero, but that's not what he claimed. It
might be ((void *)0) or something like that, but i very much doubt anyone has
it as ((void *)0xdeadbeef), especially given that NULL _is_ guaranteed to
become 0 when converted to an integer


I didn't say anything about all-bits-zero. NULL usually is something
other than 0 (even if it compares equal to 0), but 0 always works in
initializing a pointer variable, so I thought it should be mentioned
in addition to mentioning NULL.

Also using 0 rather than NULL can be done without having to #include
anything. That's clearly a way that 0 and NULL are different.
Nov 15 '05 #16

P: n/a
Jordan Abel <jm****@purdue.edu> wrote:
I could have sworn that there was a guarantee that null pointers
(constant or otherwise) convert to zero
Nope. Constant zeroes convert to null pointers; the other way 'round is
common, but not guaranteed.
how does if(p) work, then? if(p != 0) can be explained by the 0
being converted to a null pointer, and !p is defined as 0==p but i
could have sworn the argument in a conditional had to be an integer
type


You would have perjured yourself. "The controlling expression of an if
statement shall have scalar type" is all the Standard has to say about
it. Well, that, and that the path taken depends on whether said
expression compares equal to 0.

Richard
Nov 15 '05 #17

P: n/a
Tim Rentsch wrote:

I didn't say anything about all-bits-zero. NULL usually is something
other than 0 (even if it compares equal to 0), but 0 always works in
initializing a pointer variable, so I thought it should be mentioned
in addition to mentioning NULL.

Do you have some evidence for "usually something other than 0"?

Brian
Nov 15 '05 #18

P: n/a
"Default User" <de***********@yahoo.com> writes:
Tim Rentsch wrote:

I didn't say anything about all-bits-zero. NULL usually is something
other than 0 (even if it compares equal to 0), but 0 always works in
initializing a pointer variable, so I thought it should be mentioned
in addition to mentioning NULL.

Do you have some evidence for "usually something other than 0"?


Only a personal informal survey. If someone has more extensive
data to report, I'd be interested to hear about (whether it
agrees with mine or not).
Nov 15 '05 #19

P: n/a
Tim Rentsch wrote:
"Default User" <de***********@yahoo.com> writes:

Do you have some evidence for "usually something other than 0"?


Only a personal informal survey. If someone has more extensive
data to report, I'd be interested to hear about (whether it
agrees with mine or not).


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.

Brian

Nov 15 '05 #20

P: n/a
"Default User" <de***********@yahoo.com> writes:
Tim Rentsch wrote:
"Default User" <de***********@yahoo.com> writes:

Do you have some evidence for "usually something other than 0"?


Only a personal informal survey. If someone has more extensive
data to report, I'd be interested to hear about (whether it
agrees with mine or not).


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.
Nov 15 '05 #21

P: n/a
On 2005-10-26, Tim Rentsch <tx*@alumnus.caltech.edu> wrote:
"Default User" <de***********@yahoo.com> writes:
[...]

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/wg...cs/dr_043.html

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

http://groups.google.com/group/comp....p.std.c&hl=en&)

--
Nils R. Weller, Bremen (Germany)
My real email address is ``nils<at>gnulinux<dot>nl''
.... but I'm not speaking for the Software Libre Foundation!
Nov 15 '05 #22

P: n/a
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
Nov 15 '05 #23

P: n/a
Nils Weller <me@privacy.net> writes:
On 2005-10-26, Tim Rentsch <tx*@alumnus.caltech.edu> wrote:
"Default User" <de***********@yahoo.com> writes:
[...]

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.
Nov 15 '05 #24

P: n/a
On 2005-10-26, Tim Rentsch <tx*@alumnus.caltech.edu> wrote:
Nils Weller <me@privacy.net> writes:
On 2005-10-26, Tim Rentsch <tx*@alumnus.caltech.edu> wrote:
[...]
> #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 :-)

(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.)

--
Nils R. Weller, Bremen (Germany)
My real email address is ``nils<at>gnulinux<dot>nl''
.... but I'm not speaking for the Software Libre Foundation!
Nov 15 '05 #25

P: n/a
Tim Rentsch <tx*@alumnus.caltech.edu> writes:
[...]
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?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #26

P: n/a
Tim Rentsch wrote:
<snip>
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.
Nov 15 '05 #27

P: n/a
Nils Weller <me@privacy.net> writes:
On 2005-10-26, Tim Rentsch <tx*@alumnus.caltech.edu> wrote:
Nils Weller <me@privacy.net> writes:
On 2005-10-26, Tim Rentsch <tx*@alumnus.caltech.edu> wrote:
[...]
> #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!)
Nov 15 '05 #28

P: n/a
Skarmander <in*****@dontmailme.com> writes:
Tim Rentsch wrote:
<snip>
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.


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.
Nov 15 '05 #29

P: n/a
Keith Thompson <ks***@mib.org> writes:
Tim Rentsch <tx*@alumnus.caltech.edu> writes:
[...]
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.


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.
Nov 15 '05 #30

P: n/a
On 2005-10-26, Keith Thompson <ks***@mib.org> wrote:
Tim Rentsch <tx*@alumnus.caltech.edu> writes:
[...]
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?


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
Nov 15 '05 #31

P: n/a
Tim Rentsch <tx*@alumnus.caltech.edu> writes:
Keith Thompson <ks***@mib.org> writes: [...]
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.


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.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #32

P: n/a
Tim Rentsch wrote:
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.
Nov 15 '05 #33

P: n/a
Skarmander <in*****@dontmailme.com> writes:
Tim Rentsch wrote:
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.


Does this mean you'd present a counterargument even if no one was
advocating the argument?
Nov 15 '05 #34

P: n/a
Tim Rentsch wrote:
Skarmander <in*****@dontmailme.com> writes:

Tim Rentsch wrote:
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.

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.
Nov 15 '05 #35

P: n/a
Keith Thompson <ks***@mib.org> writes:
Tim Rentsch <tx*@alumnus.caltech.edu> writes:
Keith Thompson <ks***@mib.org> writes: [...]
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/wg...2003/n1488.pdf

"Alas! he gets nothing by that."
Nov 15 '05 #36

P: n/a
Skarmander <in*****@dontmailme.com> writes:
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.
Nov 15 '05 #37

P: n/a
Tim Rentsch wrote:
Skarmander <in*****@dontmailme.com> writes:

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.
Nov 15 '05 #38

P: n/a
Skarmander <in*****@dontmailme.com> writes:
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...
Nov 15 '05 #39

This discussion thread is closed

Replies have been disabled for this discussion.