static cast

54 просмотра
Перейти к первому непрочитанному сообщению

Dan Sachs

не прочитано,
6 июн. 1998 г., 03:00:0006.06.1998

1. why doesn't this pass compilation ->
unsigned* v_ptr;
cout << *static_cast<int*>(v_ptr) <<endl;
2. what is an incomplete type?

please answer to dans...@netvision.net.il

{ Please followup to the group and Cc if you like. -jep }

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

John Potter

не прочитано,
8 июн. 1998 г., 03:00:0008.06.1998

Dan Sachs <dans...@netvision.net.il> wrote:

: 1. why doesn't this pass compilation ->


: unsigned* v_ptr;
: cout << *static_cast<int*>(v_ptr) <<endl;

Because unsigned* and int* are not related. There are standard
conversions between unsigned (int) and int but not between pointers to
them. Use reinterpret_cast for unrelated pointers (references).

John

Alexandre Oliva

не прочитано,
8 июн. 1998 г., 03:00:0008.06.1998

Dan Sachs <dans...@netvision.net.il> writes:

> 1. why doesn't this pass compilation ->

> unsigned* v_ptr;
> cout << *static_cast<int*>(v_ptr) <<endl;

Because signed and unsigned ints may have different representations,
so you can't safely cast a pointer to one of these types to a pointer
to the other. In this case, you may use reinterpret_cast, which is
inherently unportable.

> 2. what is an incomplete type?

It is a type whose definition is not known at a certain point of a
translation unit. A class that was forward-declared by not defined
yet is the typical case of incomplete type.

--
Alexandre Oliva
mailto:ol...@dcc.unicamp.br mailto:aol...@acm.org
http://www.dcc.unicamp.br/~oliva
Universidade Estadual de Campinas, SP, Brasil

jka...@otelo.ibmmail.com

не прочитано,
9 июн. 1998 г., 03:00:0009.06.1998

In article <6lg7cg$f...@netlab.cs.rpi.edu>,

Alexandre Oliva <ol...@dcc.unicamp.br> wrote:
>
> Dan Sachs <dans...@netvision.net.il> writes:
>
> > 1. why doesn't this pass compilation ->
>
> > unsigned* v_ptr;
> > cout << *static_cast<int*>(v_ptr) <<endl;
>
> Because signed and unsigned ints may have different representations,

I don't think so, at least not in C. I don't have my copy of the C
standard here to verify, but I seem to remember that within the common
range of values, the corresponding signed and unsigned types must
use the same representation.

--
James Kanze +33 (0)1 39 23 84 71 mailto: ka...@gabi-soft.fr
+49 (0)69 66 45 33 10 mailto: jka...@otelo.ibmmail.com
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orientée objet --
-- Beratung in objektorientierter Datenverarbeitung

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/ Now offering spam-free web-based newsreading

Ron Natalie

не прочитано,
10 июн. 1998 г., 03:00:0010.06.1998

jka...@otelo.ibmmail.com wrote:
>
> >
> > > unsigned* v_ptr;
> > > cout << *static_cast<int*>(v_ptr) <<endl;
> >
> > Because signed and unsigned ints may have different representations,
>

Well the real reason is that the specification specifically lists
the conversions that static_cast will do, and int* -> char* is
not one of them. Generally, a easy way to remember it is that
static_cast reverses conversions that C++ did the opposite
direction without a cast.

> I don't think so, at least not in C. I don't have my copy of the C
> standard here to verify, but I seem to remember that within the common
> range of values, the corresponding signed and unsigned types must
> use the same representation.

I would be highly disappointed if th is were the case. I believe
that the requirement is that the positive signed values have to
be convertable to unsigned without loss, not that they have to
have the same representation.

Steve Clamage

не прочитано,
10 июн. 1998 г., 03:00:0010.06.1998

Ron Natalie <r...@sensor.com> writes:

>> I don't think so, at least not in C. I don't have my copy of the C
>> standard here to verify, but I seem to remember that within the
common
>> range of values, the corresponding signed and unsigned types must
>> use the same representation.

>I would be highly disappointed if th is were the case. I believe
>that the requirement is that the positive signed values have to
>be convertable to unsigned without loss, not that they have to
>have the same representation.

Draft standard section 3.9.1 "Fundamental types" says:

"For each of the signed integer types, there exists a corresponding
(but different) unsigned integer type: "unsigned char", "unsigned short
int", "unsigned int", and "unsigned long int," each of which occupies
the same amount of storage and has the same alignment requirements
(3.9) as the corresponding signed integer type; that is, each signed
integer type has the same object representation as its corresponding
unsigned integer type. The range of nonnegative values of a signed
integer type is a subrange of the corresponding unsigned integer type,
and the value representation of each corresponding signed/unsigned
type shall be the same."

Notice the last phrase -- same representation.

The C standard has the same wording.

--
Steve Clamage, stephen...@sun.com

Paul D. DeRocco

не прочитано,
11 июн. 1998 г., 03:00:0011.06.1998

Ron Natalie wrote:
>
> jka...@otelo.ibmmail.com wrote:
> >
> > >
> > > > unsigned* v_ptr;
> > > > cout << *static_cast<int*>(v_ptr) <<endl;
> > >
> > > Because signed and unsigned ints may have different
> > > representations,
> >
>
> Well the real reason is that the specification specifically lists
> the conversions that static_cast will do, and int* -> char* is
> not one of them. Generally, a easy way to remember it is that
> static_cast reverses conversions that C++ did the opposite
> direction without a cast.

I think the reason they didn't bother introducing implicit conversions
between int* and unsigned* is that it just complexifies the rules. In
general, you can't convert among pointers to numeric types, even if
there are implicit conversions among the types themselves, because they
may have different sizes. If they introduced a special rule saying that
T* could be converted to U* if they happened to be the same size, then
one might expect int* to be convertible to short* on machines where they
are the same size, and that would open a can of worms. I can certainly
sympathize with the counter-arguments, but I expect that was the
rationale.

> I would be highly disappointed if th is were the case. I believe
> that the requirement is that the positive signed values have to
> be convertable to unsigned without loss, not that they have to
> have the same representation.

I seem to remember reading that positive signed values have to have the
same representation as unsigned values, but I could be wrong. However,
that wouldn't interfer with the real-world cases that I know of, i.e.,
two's complement, one's complement and sign-magnitude.

--

Ciao,
Paul

Ron Natalie

не прочитано,
11 июн. 1998 г., 03:00:0011.06.1998

Steve Clamage wrote:
>
>
>
> Notice the last phrase -- same representation.
>
> The C standard has the same wording.

OK...thinking more of it, the representation of
the positive side is pretty straight forward even
on the odder architectures I've dealt with.

But I still don't understand the point of making
that assertion in the spec.

Jim Cobban

не прочитано,
18 июн. 1998 г., 03:00:0018.06.1998

In article <6lc9db$2...@netlab.cs.rpi.edu>,

Dan Sachs <dans...@netvision.net.il> wrote:
>1. why doesn't this pass compilation ->
>unsigned* v_ptr;
>cout << *static_cast<int*>(v_ptr) <<endl;

Others have discussed why you cannot do a static_cast from an unsigned *
to
an int * according to the specification.

My question is why are you doing this at all. Your intent would appear
to
be to print the value pointed to by v_ptr as if that area of storage
contained a signed integer rather than an unsigned. As others have
pointed
out signed and unsigned integers must have the same storage allocation
and
representation at least for positive values. So why didn't you just
specify:

cout << int(*v_ptr) << endl;
--
Jim Cobban | jco...@nortel.ca | Phone: (613)
763-8013
Nortel (MCS) | | FAX: (613)
763-5199

Ron Natalie

не прочитано,
18 июн. 1998 г., 03:00:0018.06.1998

Jim Cobban wrote:
>. As others have
> pointed
> out signed and unsigned integers must have the same storage allocation
> and
> representation at least for positive values. So why didn't you just
> specify:
>
> cout << int(*v_ptr) << endl;

Even if they didn't have the same representation, this would
be the correct scheme. Conversion between integral types
themselves is pretty well behaved even if conversion between
their pointers isn't!

Dan Sachs

не прочитано,
19 июн. 1998 г., 03:00:0019.06.1998

Steve Clamage wrote:

>
> Ron Natalie <r...@sensor.com> writes:
> >I would be highly disappointed if th is were the case. I believe
> >that the requirement is that the positive signed values have to
> >be convertable to unsigned without loss, not that they have to
> >have the same representation.

if you try to convert an unsigned value to a signed value there could be
loss of data. this depends on the size of the number you want to convert

> Draft standard section 3.9.1 "Fundamental types" says:
>
> "For each of the signed integer types, there exists a corresponding
> (but different) unsigned integer type: "unsigned char", "unsigned
short
> int", "unsigned int", and "unsigned long int," each of which occupies
> the same amount of storage and has the same alignment requirements
> (3.9) as the corresponding signed integer type; that is, each signed
> integer type has the same object representation as its corresponding
> unsigned integer type. The range of nonnegative values of a signed
> integer type is a subrange of the corresponding unsigned integer type,
> and the value representation of each corresponding signed/unsigned
> type shall be the same."
>

> Notice the last phrase -- same representation.
>
> The C standard has the same wording.
>

Ok. Both int and unsigned int take the same size but unsigned int can
reach higher positive values using the last bit, therefore the
representation is different. Saying that signed and unsigned take the
same representation is like saying the same about int and float.
What the phrase above claims is that each positive signed value (!!!)
has a corresponding unsigned value. This does not apply to negative
values...

Russ Williams

не прочитано,
19 июн. 1998 г., 03:00:0019.06.1998

Jim Cobban wrote in message <6m5tkr$g...@bcarh8ab.bnr.ca
<mailto:6m5tkr$g...@bcarh8ab.bnr.ca>>...

>Others have discussed why you cannot do a static_cast from an unsigned
*
>to
>an int * according to the specification.


So in Stroustrup 3ed 6.2.7 p130, is the following sentence
wrong/obsolete,
misleading, or what?

"The static_cast operator converts between related types such as one
pointer
type to another, an enumeration to an integral type, or a floating-point
type to an integral type."

That certainly seems to imply that static_cast should let you cast from
unsigned* to int*. This seems to be exactly a conversion from one
pointer
type to another. And there's sample code:

int * p = static_cast<int *>(malloc(100));

Surely casting void* to int* would be even more dangerous/questionable
than
casting unsigned* to int*...?

Is it legal to static_cast void* to int*? If not, then Stroustrup seems
surprisingly wrong here. If so, then why is it illegal to static_cast
unsigned* to int*, since you can convert unsigned* to void* with no cast
needed, then static_cast void* to int*.

What am I missing?

Russ

John Potter

не прочитано,
21 июн. 1998 г., 03:00:0021.06.1998

Russ Williams <Ru...@Kinesoft.com> wrote:

: Jim Cobban wrote in message <6m5tkr$g...@bcarh8ab.bnr.ca


: <mailto:6m5tkr$g...@bcarh8ab.bnr.ca>>...
: >Others have discussed why you cannot do a static_cast from an
unsigned
: *
: >to
: >an int * according to the specification.


: So in Stroustrup 3ed 6.2.7 p130, is the following sentence
: wrong/obsolete,
: misleading, or what?

Misleading. There are some static_casts between related pointer types
such as base/derived.

: "The static_cast operator converts between related types such as one


: pointer
: type to another, an enumeration to an integral type, or a
floating-point
: type to an integral type."

: That certainly seems to imply that static_cast should let you cast
from
: unsigned* to int*. This seems to be exactly a conversion from one
: pointer
: type to another. And there's sample code:

No implication there at all; however, you might make that inference :)

: int * p = static_cast<int *>(malloc(100));

: Surely casting void* to int* would be even more dangerous/questionable
: than
: casting unsigned* to int*...?

: Is it legal to static_cast void* to int*?

Yes. It is the inverse of a standard conversion.

: If so, then why is it illegal to static_cast


: unsigned* to int*, since you can convert unsigned* to void* with no
cast
: needed, then static_cast void* to int*.

Not quite. Unsigned* can be implicitly cast to void*, but implicit
conversions are not allowed on the arguement of a cast. You can do it
explicitly.

static_cast<int*>(static_cast<void*>(someUnsignedPointer));

Does this make you happy? I'm quite content to write

reinterpret_cast<int*>(someUnsignedPointer);

I know the latter is implementation defined and trust something
reasonable will be done. I know the former is allowed but can't find
anything to say what will happen. I trust that the same reasonable
thing will be done in both cases.

: What am I missing?

Static_cast is not safe_cast. Dynamic_cast is safe. The other three
are not. There are rules which state which actions can be performed
by each and that's it. You can search for _cast and find all of them,
but you can't conclude without checking that the static_casts are any
safer than the reinterpret_casts.

A dejanews search in this group and csc++ should yield lots more
confusion. I finally quit trying to make sence of it and just learned
the rules. The rules are in the standard and I'm happy we have one.

John

jka...@otelo.ibmmail.com

не прочитано,
24 июн. 1998 г., 03:00:0024.06.1998

In article <6mh9ni$gio$1...@pigpen.csrlink.net>,
jpo...@falcon.lhup.edu (John Potter) wrote:
>

> Not quite. Unsigned* can be implicitly cast to void*, but implicit
> conversions are not allowed on the arguement of a cast. You can do it
> explicitly.
>
> static_cast<int*>(static_cast<void*>(someUnsignedPointer));

In the C standard (if memory serves me correctly), the only thing you
could
legally do with a void* was cast it back to the original type --
anything
else resulted in undefined behavior. I can't find the corresponding
words for this in the C++ standard, but it may be implicit -- the only
defined semantics are when casting back to the original type, so
anything
else is undefined behavior.

--
James Kanze +33 (0)1 39 23 84 71 mailto: ka...@gabi-soft.fr
+49 (0)69 66 45 33 10 mailto: jka...@otelo.ibmmail.com
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orientée objet --
-- Beratung in objektorientierter Datenverarbeitung

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/ Now offering spam-free web-based newsreading

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Francisco Olarte Sanz

не прочитано,
25 июн. 1998 г., 03:00:0025.06.1998

jka...@otelo.ibmmail.com wrote:

> In the C standard (if memory serves me correctly), the only thing you
> could
> legally do with a void* was cast it back to the original type --
> anything
> else resulted in undefined behavior.

malloc/realloc/calloc return pointers that can be casted
to other pointer type in C ( they act as having no original type )

Francisco Olarte Sanz.

John Potter

не прочитано,
25 июн. 1998 г., 03:00:0025.06.1998

jka...@otelo.ibmmail.com wrote:

: In article <6mh9ni$gio$1...@pigpen.csrlink.net>,
: jpo...@falcon.lhup.edu (John Potter) wrote:
: >

: > Not quite. Unsigned* can be implicitly cast to void*, but implicit
: > conversions are not allowed on the arguement of a cast. You can do
it
: > explicitly.
: >
: > static_cast<int*>(static_cast<void*>(someUnsignedPointer));

: In the C standard (if memory serves me correctly), the only thing you


: could
: legally do with a void* was cast it back to the original type --
: anything

: else resulted in undefined behavior. I can't find the corresponding


: words for this in the C++ standard, but it may be implicit -- the only
: defined semantics are when casting back to the original type, so
: anything
: else is undefined behavior.

Maybe what you are thinking of and can't find is that accessing an
object as other than its declared type, char or unsigned char is
undefined behavior. The above cast is valid, but dereferencing it is
undefined behavior.

I think that I can write a function like memcpy which gets void* and
casts to char* regardless of what the original types were. It follows
that the above is also allowed. The standard tells me that I can
access any object via a char* but does not give me any way to get one.

unsigned int u(someValue);
cout << static_cast<int>(u); // implementation defined
cout << *reinterpret_cast<int*>(&u); // undefined
cout << *static_cast<int*>(static_cast<void*>(&u)); // undefined
int i;
memcpy(&i, &u, sizeof(u));
cout << i; // well defined?

On the pratical side, I expect all four to give the same result. Does
anyone have a counter example system?

John

David Abrahams

не прочитано,
25 июн. 1998 г., 03:00:0025.06.1998

jka...@otelo.ibmmail.com wrote:
>
>: In the C standard (if memory serves me correctly), the only thing you
>: could
>: legally do with a void* was cast it back to the original type --
>: anything
>: else resulted in undefined behavior. I can't find the corresponding
>: words for this in the C++ standard, but it may be implicit -- the
only
>: defined semantics are when casting back to the original type, so
>: anything
>: else is undefined behavior.

Maybe the reason you can't find corresponding words in the C++
standard is that it can't be done. At least one implementation
(Borland) has pointers-to-member-functions which don't fit into a
void*. I think this may be neccessary for virtual functions of virtual
base classes, though I'm not sure why.

Kevin J. Hopps

не прочитано,
27 июн. 1998 г., 03:00:0027.06.1998

Francisco Olarte Sanz wrote:
>
> jka...@otelo.ibmmail.com wrote:
>
> > In the C standard (if memory serves me correctly), the only thing you
> > could
> > legally do with a void* was cast it back to the original type --
> > anything
> > else resulted in undefined behavior.
>
> malloc/realloc/calloc return pointers that can be casted
> to other pointer type in C ( they act as having no original type )

The returned void* from these functions is guaranteed to be suitably
aligned for *any* type. The same guarantee is not made when casting
between two specific pointer types.

jka...@otelo.ibmmail.com

не прочитано,
29 июн. 1998 г., 03:00:0029.06.1998

In article <3593AD...@adobe.com>,

kho...@Adobe.COM wrote:
>
> Francisco Olarte Sanz wrote:
> >
> > jka...@otelo.ibmmail.com wrote:
> >
> > > In the C standard (if memory serves me correctly), the only thing you
> > > could
> > > legally do with a void* was cast it back to the original type --
> > > anything
> > > else resulted in undefined behavior.
> >
> > malloc/realloc/calloc return pointers that can be casted
> > to other pointer type in C ( they act as having no original type )
>
> The returned void* from these functions is guaranteed to be suitably
> aligned for *any* type. The same guarantee is not made when casting
> between two specific pointer types.

This is actually not as clear as it should be in the C standard. The
intent of the C standard was to make an implementation using typed (or
tagged) pointers legal -- in such an implementation, casting to void*
would not remove the tagging information, which would magically reappear
when the pointer was cast back to the original type. Obviously, in such
an implementation, the return value of malloc et al. must be untagged,
with the cast of an untagged void* adding the tagging information.

Regretfully, I don't think that this is what the C standard actually
said. It said what Kevin Hopps states: that the memory must be suitably
aligned, and no more. In other contexts (explination of the semantics
of pointer casts), it would seem that just being aligned is not
sufficient
to guarantee that the cast works.

(WARNING: the above is from memory. I don't have my copy of the C
standard
here to verify, and the reasoning involves some fairly fine points. So
if it matters to you, you should verify it before believing me.)

--
James Kanze +33 (0)1 39 23 84 71 mailto: ka...@gabi-soft.fr
+49 (0)69 66 45 33 10 mailto: jka...@otelo.ibmmail.com
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France

Conseils en informatique orientee objet --


-- Beratung in objektorientierter Datenverarbeitung

-----== Posted via Deja News, The Leader in Internet Discussion ==-----

http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum

Ответить всем
Написать сообщение автору
Переслать
0 новых сообщений