Let's assume that we're working on the following system:
CHAR_BIT == 8
sizeof( char* ) == 4 (i.e. 32-Bit)
Furthermore, lets assume that the memory addresses are distributed as
follows:
0x00000000 through 0xFFFFFFFE : Valid byte addresses
0xFFFFFFFF : Null pointer value
If we want to set a pointer to null, we can just do the following:
char *p = 0; /* Now contains 0xFFFFFFFF */
If, for some wacky reason, we wanted to set it to all bits zero, then we
could do:
memset(p, 0, sizeof p); /* Now contains 0x00000000 */
I'd like to know what happens however when we explicitly use a cast:
p = reinterpret_cast<char*>(0);
p = (char*)0;
Do the above two lines of code set our pointer to the legitimate null
pointer value, or do they set it to all bits zero? (My guess is that it's
the null pointer value)
Or consider the following:
#include <iostream>
int main()
{
unsigned i;
std::cin >> i;
/* Let's assume that user types in 0 */
char *p = reinterpret_cast<char*>( i );
}
I would presume that the above code snippet sets p to all bits zero in
the above, rather than the legitimate null pointer value.
I'm very familiar with the concept of "type mismatch"; for instance, I
realise that the following is broken:
double *p;
float k = 34.2;
p = k;
The literal, 0, is of the type "signed int". I've always thought it
strange that the following triggers a type-mismatch error:
char *p = 5;
While the following doesn't:
char *p = 0;
From the knowledge I have at the moment, it seems to me that an
expression known at compile-time to be equal to zero gets special
treatment -- even when cast explicitly. This would lead me to believe
that the following line sets p to the null pointer value:
char *p = reinterpret_cast<char*>( 7 - 5 - 2 );
, althought my example which contained user input would set the pointer
to all bits zero rather than the legitimate null pointer value. 9 2576
"Frederick Gotham" <fg*******@SPAM.com> skrev i meddelandet
news:Xn***************************@195.188.240.200 ... Let's assume that we're working on the following system:
CHAR_BIT == 8 sizeof( char* ) == 4 (i.e. 32-Bit)
Furthermore, lets assume that the memory addresses are distributed as follows:
0x00000000 through 0xFFFFFFFE : Valid byte addresses 0xFFFFFFFF : Null pointer value
If we want to set a pointer to null, we can just do the following:
char *p = 0; /* Now contains 0xFFFFFFFF */
If, for some wacky reason, we wanted to set it to all bits zero, then we could do:
memset(p, 0, sizeof p); /* Now contains 0x00000000 */
Assuming that char(0) is all zero bits, yes. Who knows on this whacky
system? I'd like to know what happens however when we explicitly use a cast:
p = reinterpret_cast<char*>(0);
p = (char*)0;
Do the above two lines of code set our pointer to the legitimate null pointer value, or do they set it to all bits zero? (My guess is that it's the null pointer value)
When p is a char*, the expressions
p = (char*)0;
and
p = 0;
are identical.
The reinterpret_cast is a bit fishy, because it is allowed to have
some implementation defined mappings. I believe we would have to
consult the (whacky) compiler manual. Or consider the following:
#include <iostream>
int main() { unsigned i;
std::cin >> i;
/* Let's assume that user types in 0 */
char *p = reinterpret_cast<char*>( i ); }
I would presume that the above code snippet sets p to all bits zero in the above, rather than the legitimate null pointer value.
I wouldn't presume too much. :-)
I'm very familiar with the concept of "type mismatch"; for instance, I realise that the following is broken:
double *p; float k = 34.2;
p = k;
The literal, 0, is of the type "signed int". I've always thought it strange that the following triggers a type-mismatch error:
char *p = 5;
While the following doesn't:
char *p = 0;
That's just the way it is. Zero is special! From the knowledge I have at the moment, it seems to me that an expression known at compile-time to be equal to zero gets special treatment -- even when cast explicitly. This would lead me to believe that the following line sets p to the null pointer value:
char *p = reinterpret_cast<char*>( 7 - 5 - 2 );
If you skip the reinterpret_cast, you are right
char* p = 7 - 5 - 2;
creates a null pointer. With the cast, I don't know for sure. , althought my example which contained user input would set the pointer to all bits zero rather than the legitimate null pointer value.
The user would surely input -5 instead, and break the code entirely.
:-)
Bo Persson
"Bo Persson" <bo*@gmb.dk> wrote: "Frederick Gotham" skrev i meddelandet ... If, for some wacky reason, we wanted to set it to all bits zero, then we could do:
memset(p, 0, sizeof p); /* Now contains 0x00000000 */
Assuming that char(0) is all zero bits, yes. Who knows on this whacky system?
No need to assume. That is 0, not '0';
"Roberto Waltman" <us****@rwaltman.net> skrev i meddelandet
news:tg********************************@4ax.com... "Bo Persson" <bo*@gmb.dk> wrote:"Frederick Gotham" skrev i meddelandet ... If, for some wacky reason, we wanted to set it to all bits zero, then we could do:
memset(p, 0, sizeof p); /* Now contains 0x00000000 */
Assuming that char(0) is all zero bits, yes. Who knows on this whacky system?
No need to assume. That is 0, not '0';
But memset takes an int parameter, that it has to convert to type
char. On normal hardware this is easy, but on a hypothetical hardware
using 0xFFFFFFFF for the null pointer, who knows what bit pattern is
used for char(0)?!
Just trying to be picky! :-)
Bo Persson
Frederick Gotham wrote: ... Furthermore, lets assume that the memory addresses are distributed as follows:
0x00000000 through 0xFFFFFFFE : Valid byte addresses 0xFFFFFFFF : Null pointer value
If we want to set a pointer to null, we can just do the following:
char *p = 0; /* Now contains 0xFFFFFFFF */
If, for some wacky reason, we wanted to set it to all bits zero, then we could do:
memset(p, 0, sizeof p); /* Now contains 0x00000000 */
I'd like to know what happens however when we explicitly use a cast:
p = reinterpret_cast<char*>(0);
p = (char*)0;
Do the above two lines of code set our pointer to the legitimate null pointer value, or do they set it to all bits zero? (My guess is that it's the null pointer value)
Yes. Both produce the null pointer value. Note though that the second
one in this case is interpreted as 'static_cast', not as 'reinterpret_cast'.
Or consider the following:
#include <iostream>
int main() { unsigned i;
std::cin >> i;
/* Let's assume that user types in 0 */
char *p = reinterpret_cast<char*>( i ); }
I would presume that the above code snippet sets p to all bits zero in the above, rather than the legitimate null pointer value.
You are right when you assume that the code is not guaranteed to produce
the null pointer value. However, the 'int -> char*' mapping produced by
'reinterpret_cast' in this case is implementation defined, which means
that in general case there's no guarantee that 'p' is all bits zero as well. The literal, 0, is of the type "signed int". I've always thought it strange that the following triggers a type-mismatch error:
char *p = 5;
While the following doesn't:
char *p = 0;
From the knowledge I have at the moment, it seems to me that an expression known at compile-time to be equal to zero gets special treatment -- even when cast explicitly.
Yes, that's exactly correct. See the definition of 'null pointer
constant' in the language specification.
This would lead me to believe that the following line sets p to the null pointer value:
char *p = reinterpret_cast<char*>( 7 - 5 - 2 );
That's true. The same can be said about, for example,
char *p =
reinterpret_cast<char*>(sizeof(7)*2 - sizeof(5) - sizeof(int));
or
char *p = reinterpret_cast<char*>(false);
--
Best regards,
Andrey Tarasevich
Bo Persson schrieb: 0x00000000 through 0xFFFFFFFE : Valid byte addresses 0xFFFFFFFF : Null pointer value
If we want to set a pointer to null, we can just do the following:
char *p = 0; /* Now contains 0xFFFFFFFF */
If, for some wacky reason, we wanted to set it to all bits zero, then we could do:
memset(p, 0, sizeof p); /* Now contains 0x00000000 */
Assuming that char(0) is all zero bits, yes. Who knows on this whacky system?
Assuming p still is = 0, this is undefined behaviour. Dereferencing a
null-pointer, isn't it?
Thomas
Bo Persson posted: But memset takes an int parameter, that it has to convert to type char. On normal hardware this is easy, but on a hypothetical hardware using 0xFFFFFFFF for the null pointer, who knows what bit pattern is used for char(0)?!
The Standard says exactly how unsigned integers store their values (i.e.
i.e. something like "obey modulo X arithemtic").
It also says that the signed variety integer type has the same bit pattern
for the values which can be expressed accurately with the unsigned variety.
Therefore, the unsigned char variety of zero is all bits zero.
And hence, the signed char variety of zero is all bits zero.
Frederick Gotham wrote: I'd like to know what happens however when we explicitly use a cast:
p = reinterpret_cast<char*>(0);
p = (char*)0;
But note that the cast in the second line here is special. It creates a
null pointer constant of type char *. The zero is an integral constant
expression having value zero, and as such it is a null pointer
constant. It can be converted to a null pointer value of a specific
pointer type by means of a static_cast or equivalent. Note that I said
value, not null pointer constant. The expression 0 is a null pointer
constant. The expression (char *) 0 is a null pointer value of type
char *.
On the other hand, the result of the reinterpret_cast is similar to
this:
int non_constant_zero = 0;
p = (char *) non_constant_zero;
I.e. implementation-defined conversion. It could well be that it will
just convert the 0 to an all-zero bit pattern. This would be the the
most sensible way to do it.
The reason for this is that the C++ standard does not require
reinterpret_cast to treat null pointer constants specially, and fall
back on the portable conversion.
Do the above two lines of code set our pointer to the legitimate null pointer value, or do they set it to all bits zero? (My guess is that it's the null pointer value)
Or consider the following:
#include <iostream>
int main() { unsigned i;
std::cin >> i;
/* Let's assume that user types in 0 */
char *p = reinterpret_cast<char*>( i );
Here, you can also write
char *p = (char *) i;
This is semantically equivalent to reinterpret_cast. The C style cast
in C++ is just an interface to the C++-style casts.
The only one of the C++ style casts (const_cast, static_cast,
dynamic_cast, reinterpret_cast) which can do an int to char *
conversion is reinterpret_cast. So that is the one that is will be
chosen to implement the C style cast notation.
The literal, 0, is of the type "signed int". I've always thought it strange that the following triggers a type-mismatch error:
char *p = 5;
While the following doesn't:
char *p = 0;
This idea is inherited from the ANSI C language. An integral constant
expression that has value zero plays a special semantic role in the
language. It serves as a null pointer constant. In ANSI C, in fact,
even such a constant cast to (void *) is still a null pointer constant,
and not a null pointer value of type void *. So for instance, this is
valid:
void (*f)(int) = (void *) 0;
whereas non-constant (void *) values cannot be converted to function
pointers. The entire "(void *) 0" is a special expression that just
means "null pointer constant". (In the C language, I repeat! In C++
(void *) 0 is a null pointer value of type void *, and not a null
pointer constant.
From the knowledge I have at the moment, it seems to me that an expression known at compile-time to be equal to zero gets special treatment -- even when cast explicitly.
That is correct. When cast explicitly, its special semantic role is
taken into account, depending on the cast operator! reinterpret_cast
doesn't care; it treats the null pointer constant as an integer zero.
This would lead me to believe that the following line sets p to the null pointer value:
char *p = reinterpret_cast<char*>( 7 - 5 - 2 );
But here, you specifically request the non-portable conversion of
reinterpret_cast, so its special semantics apply. Under that semantics,
the zero is really just an ordinary zero. The reinterpret_cast does not
handle zero constants specially, and it does not have "fall back"
behavior onto portable conversions.
A null pointer constant can be converted to char * by a weaker
conversion. So if you write
char *p = (char *) (7 - 5 - 2);
This C-style cast is /not/ the same as a reinterpret_cast. A
static_cast will do this job, so that's what it's equivalent to:
char *p = static_cast<char *>(7 - 5 - 2);
And because a cast is not needed at all to convert 7 - 5 - 2 to char
*, this static_cast doesn't do anything special. It does the same
conversion that happens when some variable of type char * is
initialized with a null pointer constant, e.g:
typedef char *T;
T temp(7-5-2); // no cast needed
Note finally that a reinterpret_cast /is/ required to convert null
pointer /values/ from one type to null pointer values of another. So
this should in fact give you a null pointer:
char *p = reinterpret_cast<char *>((void *) (7 - 5 - 2));
The reuqirement comes from paragraph 8 of section 5.2.10. :)
Kaz Kylheku wrote: Frederick Gotham wrote: I'd like to know what happens however when we explicitly use a cast:
p = reinterpret_cast<char*>(0);
p = (char*)0; ... On the other hand, the result of the reinterpret_cast is similar to this:
int non_constant_zero = 0; p = (char *) non_constant_zero;
I.e. implementation-defined conversion. It could well be that it will just convert the 0 to an all-zero bit pattern. This would be the the most sensible way to do it.
The reason for this is that the C++ standard does not require reinterpret_cast to treat null pointer constants specially, and fall back on the portable conversion.
One the one hand, in the original version of the standard the normative
text does not require that null pointer constant is treated by
'reinterpret_cast' differently from other integral values. On the other
hand, the footnote 64 states that null pointer constants have to yield
null pointer values after being converted by 'reinterpret_cast'. It is
true that footnotes are not normative, but at least it demonstrates the
original intent of the committee. And the original intent was that
'reinterpret_cast<char*>(0)' does yield the null pointer value.
However, this will probably be changed in the future revisions of the
standard to the implementetion-defined behavior you describe (see http://open-std.org/jtc1/sc22/wg21/d...fects.html#463)
--
Best regards,
Andrey Tarasevich
Frederick Gotham wrote: Bo Persson posted:
But memset takes an int parameter, that it has to convert to type char. On normal hardware this is easy, but on a hypothetical hardware using 0xFFFFFFFF for the null pointer, who knows what bit pattern is used for char(0)?!
The Standard says exactly how unsigned integers store their values (i.e. i.e. something like "obey modulo X arithemtic").
It also says that the signed variety integer type has the same bit pattern for the values which can be expressed accurately with the unsigned variety.
Therefore, the unsigned char variety of zero is all bits zero.
And hence, the signed char variety of zero is all bits zero.
Well, there could be different values for +0 and -0, so you have be careful
not to get a negative zero ;-) This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Dan V. |
last post by:
Still struggling with css.
Anyone know how to put a tope background colour (matches the right part of
the banner image) that stretches to the max....
|
by: Nick Flandry |
last post by:
I'm running into an Invalid Cast Exception on an ASP.NET application that runs fine in my
development environment (Win2K server running IIS 5) and a...
|
by: PontiMax |
last post by:
Hi.
Not sure whether this is the right group but I am looking
for some powerful asp.net grid control. The grid should be
editable, allow some...
|
by: the.duckman |
last post by:
G'Day.
Anybodey got an idea on this problem.
Say I have a function object doCast(object obj, Type t);
It's job is to cast the obect (obj) to...
|
by: nutty |
last post by:
Hi,
In my code I use two implicit casts in a row. VC compiled it in all
version I have. 7.1 and 8.0, but it seems not to be standard. Comeau in...
|
by: Frederick Gotham |
last post by:
Before I begin, here's a list of assumptions for this particular example:
(1) unsigned int has no padding bits, and therefore no invalid bit-...
|
by: Sky |
last post by:
I have been looking for a more powerful version of GetType(string) that will
find the Type no matter what, and will work even if only supplied...
|
by: bsruth |
last post by:
I tried for an hour to find some reference to concrete information on
why this particular inheritance implementation is a bad idea, but
couldn't. ...
|
by: mensanator |
last post by:
Probably just me. I've only been using Access and SQL Server
for 12 years, so I'm sure my opinions don't count for anything.
I was, nevertheless,...
|
by: tammygombez |
last post by:
Hey fellow JavaFX developers,
I'm currently working on a project that involves using a ComboBox in JavaFX, and I've run into a bit of an issue....
|
by: tammygombez |
last post by:
Hey everyone!
I've been researching gaming laptops lately, and I must say, they can get pretty expensive. However, I've come across some great...
|
by: better678 |
last post by:
Question:
Discuss your understanding of the Java platform. Is the statement "Java is interpreted" correct?
Answer:
Java is an object-oriented...
|
by: Kemmylinns12 |
last post by:
Blockchain technology has emerged as a transformative force in the business world, offering unprecedented opportunities for innovation and...
|
by: CD Tom |
last post by:
This happens in runtime 2013 and 2016. When a report is run and then closed a toolbar shows up and the only way to get it to go away is to right...
|
by: CD Tom |
last post by:
This only shows up in access runtime. When a user select a report from my report menu when they close the report they get a menu I've called Add-ins...
|
by: Naresh1 |
last post by:
What is WebLogic Admin Training?
WebLogic Admin Training is a specialized program designed to equip individuals with the skills and knowledge...
|
by: antdb |
last post by:
Ⅰ. Advantage of AntDB: hyper-convergence + streaming processing engine
In the overall architecture, a new "hyper-convergence" concept was...
|
by: Matthew3360 |
last post by:
Hi, I have a python app that i want to be able to get variables from a php page on my webserver. My python app is on my computer. How would I make it...
| |