473,574 Members | 2,635 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Just how powerful is the cast?


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_cas t<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_cas t<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_cas t<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.

Jun 22 '06 #1
9 2707

"Frederick Gotham" <fg*******@SPAM .com> skrev i meddelandet
news:Xn******** *************** ****@195.188.24 0.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_cas t<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_cas t 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_cas t<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_cas t<char*>( 7 - 5 - 2 );
If you skip the reinterpret_cas t, 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
Jun 22 '06 #2
"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';
Jun 22 '06 #3

"Roberto Waltman" <us****@rwaltma n.net> skrev i meddelandet
news:tg******** *************** *********@4ax.c om...
"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
Jun 22 '06 #4
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_cas t<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_ca st'.
Or consider the following:

#include <iostream>

int main()
{
unsigned i;

std::cin >> i;

/* Let's assume that user types in 0 */

char *p = reinterpret_cas t<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_ca st' 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_cas t<char*>( 7 - 5 - 2 );


That's true. The same can be said about, for example,

char *p =
reinterpret_cas t<char*>(sizeof (7)*2 - sizeof(5) - sizeof(int));

or

char *p = reinterpret_cas t<char*>(false) ;

--
Best regards,
Andrey Tarasevich
Jun 22 '06 #5
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
Jun 22 '06 #6
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.
Jun 22 '06 #7
Frederick Gotham wrote:
I'd like to know what happens however when we explicitly use a cast:

p = reinterpret_cas t<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_cas t is similar to
this:

int non_constant_ze ro = 0;
p = (char *) non_constant_ze ro;

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_cas t 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_cas t<char*>( i );
Here, you can also write

char *p = (char *) i;

This is semantically equivalent to reinterpret_cas t. 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_cas t) which can do an int to char *
conversion is reinterpret_cas t. 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_cas t
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_cas t<char*>( 7 - 5 - 2 );


But here, you specifically request the non-portable conversion of
reinterpret_cas t, so its special semantics apply. Under that semantics,
the zero is really just an ordinary zero. The reinterpret_cas t 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_cas t. A
static_cast will do this job, so that's what it's equivalent to:

char *p = static_cast<cha r *>(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_cas t /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_cas t<char *>((void *) (7 - 5 - 2));

The reuqirement comes from paragraph 8 of section 5.2.10. :)

Jun 23 '06 #8
Kaz Kylheku wrote:
Frederick Gotham wrote:
I'd like to know what happens however when we explicitly use a cast:

p = reinterpret_cas t<char*>(0);

p = (char*)0;

...
On the other hand, the result of the reinterpret_cas t is similar to
this:

int non_constant_ze ro = 0;
p = (char *) non_constant_ze ro;

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_cas t 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_ca st' 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_ca st'. 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_ca st<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
Jun 23 '06 #9
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 ;-)

Jun 23 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
4300
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. size of the window like the main div? My header has a big black 'box' at the top right. I would like to keep black as the main background colour of the header div though. Unless someone knows...
5
3407
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 test environment (also Win2K server running IIS 5), but fails on IIS 6 running on a Win2003 server. The web uses Pages derived from a custom class I wrote (which itself derives from Page) to...
4
1550
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 header adjustments (e.g. multi-part row and column headers) and... it should be fast! ;-) Seriously: I've bought a grid control that is very capable - but the sluggish response time is agony... :-(
16
1536
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 a new type (t) and return it. Sounds so simple, but I cant seem to find a way to do it without some prety extravigant hacks.
4
1581
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 strict mode and gcc don't accept it. Of course, I can just throw a cast in C c = (C)b; but this is not what I want. I want to enable implicit conversion.
5
2354
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- patterns or trap representations. (2) All types have the same alignment requirements. (3) sizeof(double) >= sizeof(unsigned) ===================================== We can cast from double to...
7
7805
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 "{TypeName}", not the full "{TypeName},{AssemblyName}" As far as I know yet -- hence this question -- there is no 'one solution fits all', but instead there are several parts that have to be put...
18
2316
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. So I'm sorry if this has been answered before. Here's the scenario: We have a base class with all virtual functions. We'll call this the Animal class. We then make two classes Fish and Bird...
66
7031
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, looking forward to Sqlite3. And now that gmpy has been upgraded, I can go ahead and install Python 2.5. So I open the manual to Section 13.13 where I find the first example of how to use...
0
7813
marktang
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
8066
Oralloy
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8249
jinu1996
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7826
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
8106
tracyyun
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
5305
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3743
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3755
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2251
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.