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 38 1361
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
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.
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
yes,
exactly what you wrote means:
int* p;
p = 20;
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.
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.
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.
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.
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.
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
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.
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
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.
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.
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.
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
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
"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).
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
"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.
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!
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
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.
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!
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.
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.
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!)
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.
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.
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
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.
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.
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?
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.
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."
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.
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.
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... This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Peter Abel |
last post by:
Hi all,
I'm working under W2k with
Python 2.2.2 (#37, Oct 14 2002, 17:02:34) on win32
I have a file *test_data.txt* with the following content:
0123456789
0123456789
abcdefghi...
|
by: mike420 |
last post by:
In the context of LATEX, some Pythonista asked what the big
successes of Lisp were. I think there were at least three *big*
successes.
a. orbitz.com web site uses Lisp for algorithms, etc.
b....
|
by: Pernell Williams |
last post by:
Hi all:
I am new to Python, and this is my first post (and it won't be my last!), so
HELLO EVERYONE!! I am attempting to use "xreadlines", an outer loop and an
inner loop in conjunction with...
|
by: tabonni |
last post by:
I want to check each button groups and save the checked value into a 2
dimensional array. But, it doesn't work. Could anyone tell me what's
wrong with my code. My code is as follow:
<html>...
|
by: jrhoads23 |
last post by:
Hello,
I am trying to find a way to tell if an .NET windows forms Button
(System.Windows.Forms.Button) is "depressed" (pushed down). For my
application, I can not use a check box control set to...
|
by: Brian Henry |
last post by:
I am trying to tell if my site is running as a debug build or not in asp.net
1.1 you could say
#IF DEBUG
DO SOMETHING HERE
#ENDIF
but in ASP.NET 2.0 it seems not to work anymore... why...
|
by: Mike |
last post by:
Hi All,
I am using a COM object and so I have to use a form for it to work.
The problem is I need to run it as a service as well.
When I run it in a test scenario everything works fine and...
|
by: Robert Baer |
last post by:
The following passes the test as valid, and the mouseover for the six
indicated areas also work.
I need various areas to link to another page, including the six
mentioned.
However either the MAP...
|
by: Zhang Weiwu |
last post by:
Dear all
How does javascript realiablily tell if a variable is a reference to an
HTML Element "<select>", without causing browser to pop up error message?
if (variable.constructor ==...
|
by: Brendan Miller |
last post by:
I need a portable way to tell what subprocess.Popen will call.
For instance on unix systems, Popen will work for files flagged with the
executable bit, whereas on windows Popen will work on files...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
| |