stroustrup, void*, and reinterpret_cast

  • Permalink
  • submit to reddit
  • Email
  • Follow


Hi,

I've noticed that on pg. 342 of Stroustups "C++ Programming Language"
book his example of using partial specialization for a custom vector
template where T is a pointer to anything to avoid bloat, he uses
reinterpret_cast to go back and forth between void* and T* pointers.
Why?  Why not use static_cast?

1) he made a mistake (unlikely)
2) does static_cast with complicated T* to void* cause address shifts?
If so this could cause problems with preservation of a NULL value as
well as a round-trip inconsistency.  My feeling is that
reinterpret_cast simply will not change the actual pointer value stored
from the assembly perspective in either direction, which is desired.
3) is it because of ever so slightly better performance?

As a result of his example, I have decided throughout my program to use
reinterpret_cast to go back and forth between void* and typed pointers.
 I use static_cast only when narrowing to a derived type from a base
class type.

Can anyone give me the decisive opinion on this issue with
reinterpret_cast and void*, and in particular, why Stroustup uses
reinterpret_cast instead of static_cast?

Thanks,
Andy


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply andrew_nuss 8/30/2006 3:02:30 PM

See related articles to this posting


andrew_nuss@yahoo.com posted:

> As a result of his example, I have decided throughout my program to use
> reinterpret_cast to go back and forth between void* and typed pointers.


Why adopt someone else's style before you even understand why? It is not a 
good way to learn.

If you want to convert a void* to any other pointer type, use static_cast:

    void *pv = 0;
    int *pi = static_cast<int*>(pv);

I don't have Bjarne's book here with me, so I can't look over the code 
snippet. Perhaps he used reinterpret_cast simply because it slipped his mind

that static_cast would get the job done.

-- 

Frederick Gotham

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Frederick 8/31/2006 3:02:27 PM

Frederick Gotham wrote:
> I don't have Bjarne's book here with me, so I can't look over the code
> snippet. Perhaps he used reinterpret_cast simply because it slipped his
mind
>
> that static_cast would get the job done.
>

In the following code, is null preserved?

main () {
    void* pv = 0;
    if (static_cast<int*>(pv) == 0)
        cout << "null preserved";
}


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply andrew_nuss 8/31/2006 7:10:56 PM

andrew_nuss@yahoo.com wrote:
> I've noticed that on pg. 342 of Stroustups "C++ Programming Language"
> book his example of using partial specialization for a custom vector
> template where T is a pointer to anything to avoid bloat, he uses
> reinterpret_cast to go back and forth between void* and T* pointers.
> Why?  Why not use static_cast?

This has been fixed in the "Special Edition" to use static_cast.

And I'd have to agree with Mr. Gotham that you should probably verify 
_before_ making blanket code changes ;)

josef

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Josef 8/31/2006 7:18:57 PM

Frederick Gotham wrote:
> I don't have Bjarne's book here with me, so I can't look over the code
> snippet. Perhaps he used reinterpret_cast simply because it slipped his
mind
>
> that static_cast would get the job done.
>

It can get pretty complex for me, namely I also want to store 2 types
of pointers in a virtual hierarchy as void* and then retrieve it and
narrow it to the base class pointer. The question in the following
hierarchy of widening to an interface from 2 different derivations, and
then further widening to void*, and then being able to narrow back from
void* to the interface, what's better than my use of
reinterpret_cast<>.


class Arc;

struct ArcLink {
    virtual Arc* ThisArc () = 0;
    virtual ArcLink* NextLink () = 0;
};

class Arc : public ArcLink {
       ... some data members

    public:
    virtual Arc* ThisArc ()         { return this; }
    virtual ArcLink* NextLink()  { return 0; }

    ... additional functionality
};

class ArcLinkImpl : public ArcLink {

    Arc*         arc;
    ArcLink*   tail;

    public:
    virtual Arc* ThisArc ()          { return arc; }
    virtual ArcLink* NextLink ()  { return tail; }
};

// from utilities for a red-black set
struct IntSetElem {

     void*    obj;

     private:

     IntSetElem* left;
     IntSetElem* right;
     int key;
     bool color;
};

// and the question is, what casts to and from elem->obj
main () {
    IntSetElem* elem1 = ...;   // get an element from a set
    IntSetElem* elem2 = ...;   // get another
    Arc* arc = ...;                  // create an arc
    ArcLinkImpl* arclink = ...; // create an arclink

    ArcLink* intf = arc;        // widen
    elem1->obj = reinterpret_cast<void*>(intf);
    //??? can I pass arc directly to the cast here

    intf = arclink;                // a different widen
    elem2->obj = reinterpret_cast<void*>(intf);
    //??? can I pass arclink directly to the cast here

    // now fetch Arc* as ArcLink*
    intf = reinterpret_cast<ArcLink*>(elem1->obj);
    // I bet this is ok because I made sure to stuff it
    // as an ArcLink* interface pointer
    // what's better???

    // now fetch ArcLinkImpl* as ArcLink*
    intf = reinterpret_cast<ArcLink*>(elem2->obj);
    // again ok because I stuffed the ArcLinkImpl*
    // as an ArcLink*
    // what's better???
}

Andy


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply andrew_nuss 8/31/2006 7:19:31 PM

Frederick Gotham wrote:
> andrew_nuss@yahoo.com posted:
>> As a result of his example, I have decided throughout my program to use
>> reinterpret_cast to go back and forth between void* and typed pointers.
> 
> Why adopt someone else's style before you even understand why? It is not a

> good way to learn.

Because it's from a textbook, a very renowned one.
Looking back on my early days, I realise that reading others' codes
(including the style) and imitating them have been quite an effective way
to learn programming, even when I could not understand all of them.

Hence the importance of good-style examples in textbooks, and it comes to
me as a surprise that Stroustrup used reinterpret_cast where he didn't
have to, while explaining in another part of the same book that the new-
style casts were named so ugly that it could discourage their use.

-- 
Seungbeom Kim

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Seungbeom 8/31/2006 7:20:58 PM

andrew_nuss@yahoo.com wrote:

> As a result of his example, I have decided throughout my program to use
> reinterpret_cast to go back and forth between void* and typed pointers.
>  I use static_cast only when narrowing to a derived type from a base
> class type.
> 
> Can anyone give me the decisive opinion on this issue with
> reinterpret_cast and void*, and in particular, why Stroustup uses
> reinterpret_cast instead of static_cast?

It's a typo.  It's corrected in later editions; the snippet of code on 
p. 342 of my third edition doesn't contain any reinterpret_casts.

In other words, it's a pretty good idea to make sure you understand 
_why_ something is done before you start doing it yourself.  Even 
respected texts contain errors, and furthermore, even experts sometimes 
get things wrong.

-- 
Erik Max Francis && max@alcyone.com && http://www.alcyone.com/max/
  San Jose, CA, USA && 37 20 N 121 53 W && AIM erikmaxfrancis
   Would a harvest from my heart / Find its season
    -- Sandra St. Victor

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Erik 9/1/2006 12:44:56 AM

andrew_nuss@yahoo.com wrote:
> Hi,
>
> I've noticed that on pg. 342 of Stroustups "C++ Programming Language"
> book his example of using partial specialization for a custom vector
> template where T is a pointer to anything to avoid bloat, he uses
> reinterpret_cast to go back and forth between void* and T* pointers.
> Why?  Why not use static_cast?
>
> 1) he made a mistake (unlikely)

A mistake is indeed unlikely. So logically, we can speculate that using
reinterpret_cast at the time this example was written - was likely not
a mistake in C++.

> 2) does static_cast with complicated T* to void* cause address shifts?
> If so this could cause problems with preservation of a NULL value as
> well as a round-trip inconsistency.  My feeling is that
> reinterpret_cast simply will not change the actual pointer value stored
> from the assembly perspective in either direction, which is desired.

If changing the actual pointer value is undesirable - why would a
static_cast change the pointer value any more than reinterpret_cast? A
void pointer can be a pointer to any type - so with each type just as
likely as the other, would we not expect either cast to leave the
pointer's value unchanged?

> 3) is it because of ever so slightly better performance?

Not a chance.

> As a result of his example, I have decided throughout my program to use
> reinterpret_cast to go back and forth between void* and typed pointers.
>  I use static_cast only when narrowing to a derived type from a base
> class type.

I'm afraid you that you fell victim to the "argument from authority"
logical fallacy (or, for those more familiar with its Latin name: the
"argumentum ad verecundiam'' or simply the "ipse dixit" line of
reasoning. Wikipedia has a good article on this all-too-common fallacy:
http://en.wikipedia.org/wiki/Appeal_to_authority .

> Can anyone give me the decisive opinion on this issue with
> reinterpret_cast and void*, and in particular, why Stroustup uses
> reinterpret_cast instead of static_cast?

I have no idea of the actual reason - nor do I think the the issue is
particularly significant. But I would guess that - at the time - the
names of the cast operators were not yet final, so a retroactive
"mistake" was always a possibillity once the cast operators were given
names. Furthermore, choosing one or the other cast won't make any
difference to how the program runs. So rather than spend too much time
agonizing over whether to use reinterpret_cast or static_cast is the
correct choice - just pick one and move on to finishing the rest of the
program. Because - while it is true that every programmer should strive
to write correct code - it also true that no program good enough to
ship has likely ever been delayed in order for its programmers to have
time to make editorial corrections and other cosmetic improvements to
its source code. 

Greg


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Greg 9/1/2006 12:46:02 PM

andrew_nuss@yahoo.com wrote:

> In the following code, is null preserved?
> 
> main () {
>     void* pv = 0;
>     if (static_cast<int*>(pv) == 0)
>         cout << "null preserved";
> }

Yes, of course.

So long,
	Thomas

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Thomas 9/1/2006 12:49:11 PM

andrew_nuss@yahoo.com wrote:

> It can get pretty complex for me, namely I also want to store 2 types
> of pointers in a virtual hierarchy as void* and then retrieve it and
> narrow it to the base class pointer.

Possibly a not very C++ way to approach the problem. Is this time 
critical? If not, you could provide a virtual "getPointer()" method 
(please choose a better name) in the base class that returns the common 
base of the two objects, and use covariance to specialize this method in 
the derived classes. Alternatively, use a container that is templated to
the class you want to store in.

> The question in the following
> hierarchy of widening to an interface from 2 different derivations, and
> then further widening to void*, and then being able to narrow back from
> void* to the interface, what's better than my use of
> reinterpret_cast<>.
> 
> 
> class Arc;
> 
> struct ArcLink {
>     virtual Arc* ThisArc () = 0;
>     virtual ArcLink* NextLink () = 0;
> };
> 
> class Arc : public ArcLink {
>        ... some data members
> 
>     public:
>     virtual Arc* ThisArc ()         { return this; }
>     virtual ArcLink* NextLink()  { return 0; }
> 
>     ... additional functionality
> };
> 
> class ArcLinkImpl : public ArcLink {
> 
>     Arc*         arc;
>     ArcLink*   tail;
> 
>     public:
>     virtual Arc* ThisArc ()          { return arc; }
>     virtual ArcLink* NextLink ()  { return tail; }
> };
> 
> // from utilities for a red-black set
> struct IntSetElem {
> 
>      void*    obj;
> 
>      private:
> 
>      IntSetElem* left;
>      IntSetElem* right;
>      int key;
>      bool color;
> };

This should probably be a template where the templare parameter
describes the object pointed to. Alternatively, why not use an
already available container from the STL or Boost? Which kind of
operations do you need for IntSetElem?

> // and the question is, what casts to and from elem->obj
> main () {
>     IntSetElem* elem1 = ...;   // get an element from a set
>     IntSetElem* elem2 = ...;   // get another
>     Arc* arc = ...;                  // create an arc
>     ArcLinkImpl* arclink = ...; // create an arclink
> 
>     ArcLink* intf = arc;        // widen
>     elem1->obj = reinterpret_cast<void*>(intf);
>     //??? can I pass arc directly to the cast here

No cast is needed here, though maybe you would like to use an
IntSetElem<ArcLink> here?

>     intf = arclink;                // a different widen

This works.

>     elem2->obj = reinterpret_cast<void*>(intf);
>     //??? can I pass arclink directly to the cast here

No cast required. Every pointer can be converted to a void *
without a cast.

>     // now fetch Arc* as ArcLink*
>     intf = reinterpret_cast<ArcLink*>(elem1->obj);

Bad idea. Either use the template idea, or use a static_cast<>.
You do not care about the "raw bit pattern" of the pointer here. What 
you want to tell the compiler is to narrow the pointer to a more 
specific object.

>     // I bet this is ok because I made sure to stuff it
>     // as an ArcLink* interface pointer
>     // what's better???

To use an already available container, likely.

>     // now fetch ArcLinkImpl* as ArcLink*
>     intf = reinterpret_cast<ArcLink*>(elem2->obj);
>     // again ok because I stuffed the ArcLinkImpl*
>     // as an ArcLink*
>     // what's better???

No cast at all if you can avoid it. If elem2 would be an
IntSetElem<ArcLink> and would be declared as follows:

template<class T>
struct IntSetElem {

        T*    obj;

        private:

        IntSetElem* left;
        IntSetElem* right;
        int key;
        bool color;
};

no cast whatsoever would be required, and type-correctness would
be guaranteed by the compiler.

By the way: Why is this a struct? And are you sure the compiler
generated copy and assignment operators are what you want?

So long,
	Thomas

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Thomas 9/1/2006 12:49:48 PM

andrew_nuss@yahoo.com wrote:
> Frederick Gotham wrote:
> > I don't have Bjarne's book here with me, so I can't look
> > over the code snippet. Perhaps he used reinterpret_cast
> > simply because it slipped his mind that static_cast would
> > get the job done.

> In the following code, is null preserved?

> main () {
>     void* pv = 0;
>     if (static_cast<int*>(pv) == 0)
>         cout << "null preserved";
> }

All pointer casts preserve null.

--
James Kanze                                           GABI Software
Conseils en informatique orient�e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply kanze 9/1/2006 12:58:50 PM

andrew_nuss@yahoo.com wrote:
> Frederick Gotham wrote:
> > I don't have Bjarne's book here with me, so I can't look
> > over the code snippet. Perhaps he used reinterpret_cast
> > simply because it slipped his mind that static_cast would
> > get the job done.

> It can get pretty complex for me, namely I also want to store
> 2 types of pointers in a virtual hierarchy as void* and then
> retrieve it and narrow it to the base class pointer.

Both static_cast to void and reinterpret_cast have the
constraint that you must cast the pointer back to the original
type if they are to work.  In your case, you should explicitly
narrow the pointer before converting it to void*, then cast back
to the narrowed type.

> The question in the following hierarchy of widening to an
> interface from 2 different derivations, and then further
> widening to void*, and then being able to narrow back from
> void* to the interface, what's better than my use of
> reinterpret_cast<>.

> class Arc;

> struct ArcLink {
>     virtual Arc* ThisArc () = 0;
>     virtual ArcLink* NextLink () = 0;
> };

> class Arc : public ArcLink {
>        ... some data members

>     public:
>     virtual Arc* ThisArc ()         { return this; }
>     virtual ArcLink* NextLink()  { return 0; }
>
>     ... additional functionality
> };

> class ArcLinkImpl : public ArcLink {
>
>     Arc*         arc;
>     ArcLink*   tail;
>
>     public:
>     virtual Arc* ThisArc ()          { return arc; }
>     virtual ArcLink* NextLink ()  { return tail; }
> };

> // from utilities for a red-black set
> struct IntSetElem {

>      void*    obj;
>  private:
>      IntSetElem* left;
>      IntSetElem* right;
>      int key;
>      bool color;
> };

> // and the question is, what casts to and from elem->obj
> main () {
>     IntSetElem* elem1 = ...;   // get an element from a set
>     IntSetElem* elem2 = ...;   // get another
>     Arc* arc = ...;                  // create an arc
>     ArcLinkImpl* arclink = ...; // create an arclink
>
>     ArcLink* intf = arc;        // widen

I would have thought that that was narrowing.

>     elem1->obj = reinterpret_cast<void*>(intf);
>     //??? can I pass arc directly to the cast here

You don't need the cast.  Note, however, that to use the void*
(other than copying it), you must first convert it to an
ArcLink* (I'd use static_cast for this), or you have undefined
behavior.

>     intf = arclink;                // a different widen

Again, you're using widen for the operation you described as
narrowing in the text at the top.  This is derived to base.

>     elem2->obj = reinterpret_cast<void*>(intf);
>     //??? can I pass arclink directly to the cast here

Of course.  Why would it be different than the previous case.

>     // now fetch Arc* as ArcLink*
>     intf = reinterpret_cast<ArcLink*>(elem1->obj);
>     // I bet this is ok because I made sure to stuff it
>     // as an ArcLink* interface pointer
>     // what's better???

I'd use static_cast.

This is fine: you stored an ArcLink*, and you cast back to the
same type.

>     // now fetch ArcLinkImpl* as ArcLink*
>     intf = reinterpret_cast<ArcLink*>(elem2->obj);
>     // again ok because I stuffed the ArcLinkImpl*
>     // as an ArcLink*
>     // what's better???

As above.

> }

I'd still be very leary of this.  It's all too easy to forget
the passage through ArcLink* when storing the pointer, and then
it won't work---static_cast or reinterpret_cast when extracting
the pointer.  Wrap IntSetElem in a class which takes ArcLink*
pointers, so the user cannot set the pointers without converting
his pointers to ArcLink*.

--
James Kanze                                           GABI Software
Conseils en informatique orient�e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply kanze 9/1/2006 12:59:36 PM

Greg Herlihy posted:

> A mistake is indeed unlikely. So logically, we can speculate that using
> reinterpret_cast at the time this example was written - was likely not
> a mistake in C++.


A bit extreme don't you think... ? Programmers make mistakes here and there 
-- but we catch them when we read back over our code.

I _know_ that static_cast is the one for the job, so my first guess would be

that Bjarne made a mistake by using reinterpret_cast. But then again,
there's 
no observable difference in the final program.

-- 

Frederick Gotham

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Frederick 9/1/2006 8:29:59 PM

Greg Herlihy wrote:
> andrew_nuss@yahoo.com wrote:

> > I've noticed that on pg. 342 of Stroustups "C++ Programming Language"
> > book his example of using partial specialization for a custom vector
> > template where T is a pointer to anything to avoid bloat, he uses
> > reinterpret_cast to go back and forth between void* and T* pointers.
> > Why?  Why not use static_cast?

> > 1) he made a mistake (unlikely)

> A mistake is indeed unlikely. So logically, we can speculate that using
> reinterpret_cast at the time this example was written - was likely not
> a mistake in C++.

It's not really a mistake today, since it has the same effect as
static_cast in this context.

Still, Stroustrup is human (and I think he'd be the last to deny
it).  Typos occur, and he's not immune to them, any more than
you or I are.  He corrected it in later editions; I'd consider
that a recognition on his part that there was a mistake.

> > 2) does static_cast with complicated T* to void* cause
> > address shifts?  If so this could cause problems with
> > preservation of a NULL value as well as a round-trip
> > inconsistency.  My feeling is that reinterpret_cast simply
> > will not change the actual pointer value stored from the
> > assembly perspective in either direction, which is desired.

> If changing the actual pointer value is undesirable - why
> would a static_cast change the pointer value any more than
> reinterpret_cast?

Because it does.  Not when casting to and from a void*, but when
casting up and down in an inheritance hierarchy.

> A void pointer can be a pointer to any type - so with each
> type just as likely as the other, would we not expect either
> cast to leave the pointer's value unchanged?

Strictly speaking: the standard does not require that the
address of a non-POD object point to the first byte of that
object; an implementation could place the vptr at the address -
4, or some such.  In which case, both reinterpret_cast and
static_cast will change the physical address.  (Presumable, in
the case of reinterpret_cast, because of course, all that the
standard requires is that you can cast it to void* and back to
the original type.)  In practice, I've never heard of such an
implementation.

    [...]
> I have no idea of the actual reason - nor do I think the the
> issue is particularly significant. But I would guess that - at
> the time - the names of the cast operators were not yet final,
> so a retroactive "mistake" was always a possibillity once the
> cast operators were given names.

The names were finalized very early, if I remember correctly.
On the other hand, our instincts as to which cast is correct
didn't really develope until after that.

> Furthermore, choosing one or the other cast won't make any
> difference to how the program runs.

But it will affect how a maintenance programmer sees the code.
Which is, in many cases, just as important.

--
James Kanze (Gabi Software)              email: kanze.james@neuf.fr
Conseils en informatique orient�e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply James 9/3/2006 12:57:54 AM

James Kanze wrote:
> Greg Herlihy wrote:
> > andrew_nuss@yahoo.com wrote:
>
> > > I've noticed that on pg. 342 of Stroustups "C++ Programming Language"
> > > book his example of using partial specialization for a custom vector
> > > template where T is a pointer to anything to avoid bloat, he uses
> > > reinterpret_cast to go back and forth between void* and T* pointers.
> > > Why?  Why not use static_cast?
>
> > > 1) he made a mistake (unlikely)
>
> > A mistake is indeed unlikely. So logically, we can speculate that using
> > reinterpret_cast at the time this example was written - was likely not
> > a mistake in C++.
>
> It's not really a mistake today, since it has the same effect as
> static_cast in this context.
>
> Still, Stroustrup is human (and I think he'd be the last to deny
> it).  Typos occur, and he's not immune to them, any more than
> you or I are.  He corrected it in later editions; I'd consider
> that a recognition on his part that there was a mistake.

But it is WRONG to use reinterpret_cast in this example?
In my programs, I use reinterpret_cast to cast to void * and cast back
to the original pointer type.
Are there any drawbacks using this approach? What does static_cast buy
me in this case?

Diego Martins
HP


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Diego 9/5/2006 12:23:28 PM

Diego Martins wrote:
>
> But it is WRONG to use reinterpret_cast in this example?
> In my programs, I use reinterpret_cast to cast to void * and cast back
> to the original pointer type.
> Are there any drawbacks using this approach? What does static_cast buy
> me in this case?

Not wrong, just unwise. When you use reinterpret_cast you can make
mistakes that are impossible using static_cast and using static_cast,
you can make mistakes that are impossible using C-style cast. Thus, by
using the "least powerful" cast that can do the job, you minimize
errors and the likelyhood of maintenance errors. In particular,
reinterpret_cast can convert between pointers and integers - something
you wouldn't want to happen by accident.

See http://www.research.att.com/~bs/bs_faq2.html#static-cast

Also, when you use static_cast, you stay within the semantics of the
language; when you use reinterpret_cast, you play with bits (the
representation). By doing static_cast<int*>(pv) when pv is a void*, you
assume that a void* is represented in exactly the same ways as an int*.
 That's by far the most common, but not guaranted.

  -- Bjarne Stroustrup; http://www.research.att.com/~bs


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply bjarne 9/5/2006 2:25:38 PM

Diego Martins wrote:
> James Kanze wrote:
> > Greg Herlihy wrote:
> > > andrew_nuss@yahoo.com wrote:
> > > > I've noticed that on pg. 342 of Stroustups "C++
> > > > Programming Language" book his example of using partial
> > > > specialization for a custom vector template where T is a
> > > > pointer to anything to avoid bloat, he uses
> > > > reinterpret_cast to go back and forth between void* and
> > > > T* pointers.  Why?  Why not use static_cast?

> > > > 1) he made a mistake (unlikely)

> > > A mistake is indeed unlikely. So logically, we can
> > > speculate that using reinterpret_cast at the time this
> > > example was written - was likely not a mistake in C++.

> > It's not really a mistake today, since it has the same
> > effect as static_cast in this context.

> > Still, Stroustrup is human (and I think he'd be the last to
> > deny it).  Typos occur, and he's not immune to them, any
> > more than you or I are.  He corrected it in later editions;
> > I'd consider that a recognition on his part that there was a
> > mistake.

> But it is WRONG to use reinterpret_cast in this example?
> In my programs, I use reinterpret_cast to cast to void * and cast back
> to the original pointer type.
> Are there any drawbacks using this approach? What does static_cast buy
> me in this case?

It sends the wrong message to the reader.

When I see a reinterpret_cast in code, I immediately assume that
there is something very delicate and implementation dependant
going on.  When I see a static_cast, I suppose that while you
are subverting the type system somewhat, it is within more
reasonable bounds, and is portable---I don't have to pay
particular attention to it when porting to another system, for
example.

--
James Kanze                                           GABI Software
Conseils en informatique orient�e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply kanze 9/5/2006 5:04:59 PM

On 5 Sep 2006 10:25:38 -0400, "bjarne" <bjarne@gmail.com> wrote:

>When you use reinterpret_cast you can make
>mistakes that are impossible using static_cast

Ok :-)

>and using static_cast,
>you can make mistakes that are impossible using C-style cast.

This one perplexes me. Could you please elaborate?

--
Gennaro Prota

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Gennaro 9/5/2006 8:44:43 PM

On 1 Sep 2006 08:58:50 -0400, "kanze" <kanze@gabi-soft.fr> wrote:

>All pointer casts preserve null.

True for null pointer values. It's important to distinguish those ones
from "null pointer constants", though. See core issue 463 (and/or the
current working paper).

--
Gennaro Prota

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Gennaro 9/5/2006 8:45:18 PM

* bjarne:
> using static_cast,
> you can make mistakes that are impossible using C-style cast.

Is that a typo?

Otherwise, an example would be nice.

One counter-example is a C style cast that originally worked as a 
const_cast but ends up being e.g. a reinterpret_cast, which is difficult 
to achieve with static_cast; another counter-example is a C style cast 
that unintentionally casts to an inaccessible base (breaking the 
design), which again is difficult to achieve with static_cast.

Cheers,

- Alf

-- 
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Alf 9/5/2006 8:45:42 PM

Gennaro Prota wrote:
> On 1 Sep 2006 08:58:50 -0400, "kanze" <kanze@gabi-soft.fr> wrote:

> >All pointer casts preserve null.

> True for null pointer values. It's important to distinguish
> those ones from "null pointer constants", though. See core
> issue 463 (and/or the current working paper).

Which represents a change compared to what was originally
adopted, according to the intent indicated in the footnote.
(In this case, it seems a reasonable change, given the small
number of cases affected.)

--
James Kanze                                           GABI Software
Conseils en informatique orient�e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply kanze 9/6/2006 12:22:28 PM

Alf P. Steinbach wrote:
> * bjarne:
>> using static_cast,
>> you can make mistakes that are impossible using C-style cast.
>
> Is that a typo?

A typo. Sorry. "Can not"

   -- Bjarne Stroustrup; http://www.research.att.com/~bs


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply bjarne 9/6/2006 2:50:39 PM

bjarne wrote:
[SNIP]
> Also, when you use static_cast, you stay within the semantics of the
> language; when you use reinterpret_cast, you play with bits (the
> representation). By doing static_cast<int*>(pv) when pv is a void*, you
> assume that a void* is represented in exactly the same ways as an int*.
>  That's by far the most common, but not guaranted.

This statement scares me somewhat, but hopefully its just my
understanding of english that suffers. static_casting from e.g. void*
to int* can only be performed when the representation for void* is the
same as for int* - and there is nothing that guarantees that this will
work?  So - by inference - malloc is not guaranteed to work?
I surely must misunderstand something - and yet I am the only one to
react (so far!).

/Peter


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply peter 9/6/2006 5:58:49 PM

kanze wrote:
> It sends the wrong message to the reader.
>
> When I see a reinterpret_cast in code, I immediately assume that
> there is something very delicate and implementation dependant
> going on.  When I see a static_cast, I suppose that while you
> are subverting the type system somewhat, it is within more
> reasonable bounds, and is portable---I don't have to pay
> particular attention to it when porting to another system, for
> example.

There is a specific scenario that I have never been clear about in all
these years w.r.t reinterpret_casts.

In MSFT's COM-land, there is an API called CoCreateInstance -- its last
parameter is of type void**.  This API is used to get a pointer to the
interface (abstract class to be precise) you are interested in. So
people always do something like this:

struct IUnknown
{
    virtual void QueryInterface(REFIID riid, void** ppv) = 0;
    virtual void AddRef() = 0;
    virtual void Release() = 0;
};

struct ISomeInterface : public IUnknown
{
     virtual void DoIt() = 0;
};

ISomeInterface* isi;
CoCreateInstance(......,...., reinterpret_cast<void**>(&isi));

Internally a lot of hocus-pocus happens and the API ends up calling an
implementation of a standard IUnknown method called QueryInterface that
returns a pointer to ISomeInterface like so:

class SomeInterfaceImpl : public ISomeInterface
{
     void QueryInterface(REFIID riid, void** ppv)
     {
         *ppv = static_cast<ISomeInterface*>(this);

	reinterpret_cast<IUnknown*>(*ppv)->AddRef();
     }

     // remaining implementations elided for clarity
};

Have the proper casts been used in the above code?  Can you explain why
reinterpret_cast is needed in places where its been used?


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Dilip 9/6/2006 7:14:45 PM

Dilip wrote:
> ISomeInterface* isi;
> CoCreateInstance(......,...., reinterpret_cast<void**>(&isi));
> [...]
>
> Have the proper casts been used in the above code?  Can you explain why
> reinterpret_cast is needed in places where its been used?

The code could be rewritten using static_cast:

  void* pv;
  CoCreateInstance(......,...., &pv);

  ISomeInterface* isi = static_cast<ISomeInterface*>(pv);


-- 
Andrei Polushin


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Andrei 9/7/2006 1:45:18 PM

Dilip wrote:
> In MSFT's COM-land, there is an API called CoCreateInstance -- its last
> parameter is of type void**.  This API is used to get a pointer to the
> interface (abstract class to be precise) you are interested in. So
> people always do something like this:
>
> struct IUnknown
> {
>     virtual void QueryInterface(REFIID riid, void** ppv) = 0;
>     virtual void AddRef() = 0;
>     virtual void Release() = 0;
> };
>
> struct ISomeInterface : public IUnknown
> {
>      virtual void DoIt() = 0;
> };
>
> ISomeInterface* isi;
> CoCreateInstance(......,...., reinterpret_cast<void**>(&isi));
>
> Internally a lot of hocus-pocus happens and the API ends up calling an
> implementation of a standard IUnknown method called QueryInterface that
> returns a pointer to ISomeInterface like so:
>
> class SomeInterfaceImpl : public ISomeInterface
> {
>      void QueryInterface(REFIID riid, void** ppv)
>      {
>          *ppv = static_cast<ISomeInterface*>(this);
>
> 	reinterpret_cast<IUnknown*>(*ppv)->AddRef();
>      }
>
>      // remaining implementations elided for clarity
> };
>
> Have the proper casts been used in the above code?  Can you explain why
> reinterpret_cast is needed in places where its been used?
>

This is pretty system specific, so I don't know if this will go or not.
 But, I think I can explain that.  A COM object can implement many
independent interfaces as well as inherited interfaces and  All
interfaces inherit from IUnknown.  So, they end up constructing a
fairly fancy vtbl to implement all of this.  The static_cast<> above
can move the pointer up and down the vtbl to the root of the
appropriate interface.  The reinterpret_cast<> is then used to be sure
that the appropriate IUnknown will be invoked without further moving of
the pointer.  I will try to draw a picture.  If we have 2 interfaces,
we might have a vtbl that looks like this:

1: IUnknown
2: IInterface1
3: IUnknown
4: IInterface2

if we static cast to Interface2, the pointer will correspond to
position 3.  When we invoke the IUnknown addref method, we want the
IUnknown from position 3 and not the IUnknown and position 1.  To
indicate that there is something tricky going on and that we are
getting a specific IUnknown, they are using a reinterpret_cast.
Hopefully that sheds some light and isn't too far off base.

To bring it back to normal C++, we can imagine an interface like:

class base
{
  virtual ~Base(){}
 virtual void Print() = 0;
}

class IInterface1 : public Base
{
}

class IInterface2 : public Base
{
}

class Implement : public IInterface1, public IInterface2
{
}

Now, if we wanted to get a pointer to the Base that came with
IInterface2 we might static_cast to IInterface2 the reinterpret cast to
Base.  I do not believe that the reinterpret_cast is required to do
this, but it does signal that something tricky is going on.

Hopefully, I haven't spread too many lies above, I have slept at least
once since doing any COM stuff.  :)

joe


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Joe 9/7/2006 1:46:28 PM

peter koch larsen wrote:
> bjarne wrote:
> [SNIP]
> > Also, when you use static_cast, you stay within the
> > semantics of the language; when you use reinterpret_cast,
> > you play with bits (the representation). By doing
> > static_cast<int*>(pv) when pv is a void*, you assume that a
> > void* is represented in exactly the same ways as an int*.
> > That's by far the most common, but not guaranted.

> This statement scares me somewhat, but hopefully its just my
> understanding of english that suffers. static_casting from
> e.g. void* to int* can only be performed when the
> representation for void* is the same as for int* - and there
> is nothing that guarantees that this will work?  So - by
> inference - malloc is not guaranteed to work?  I surely must
> misunderstand something - and yet I am the only one to react
> (so far!).

I think that there was a type here as well, and that Bjarne was
in fact talking about reinterpret_cast.  (Technically, the
mapping done by reinterpret_cast is implementation defined, and
an implementation could make it work here regardless.  But the
statement "you play with bits" is, I think, an accurate informal
description of the intent of reinterpret_cast.)

--
James Kanze                                           GABI Software
Conseils en informatique orient�e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply kanze 9/7/2006 1:51:59 PM

Dilip wrote:
> kanze wrote:
> > It sends the wrong message to the reader.

> > When I see a reinterpret_cast in code, I immediately assume
> > that there is something very delicate and implementation
> > dependant going on.  When I see a static_cast, I suppose
> > that while you are subverting the type system somewhat, it
> > is within more reasonable bounds, and is portable---I don't
> > have to pay particular attention to it when porting to
> > another system, for example.

> There is a specific scenario that I have never been clear
> about in all these years w.r.t reinterpret_casts.

> In MSFT's COM-land, there is an API called CoCreateInstance --
> its last parameter is of type void**.  This API is used to get
> a pointer to the interface (abstract class to be precise) you
> are interested in. So people always do something like this:

> struct IUnknown
> {
>     virtual void QueryInterface(REFIID riid, void** ppv) = 0;
>     virtual void AddRef() = 0;
>     virtual void Release() = 0;
> };

> struct ISomeInterface : public IUnknown
> {
>      virtual void DoIt() = 0;
> };

> ISomeInterface* isi;
> CoCreateInstance(......,...., reinterpret_cast<void**>(&isi));

> Internally a lot of hocus-pocus happens and the API ends up
> calling an implementation of a standard IUnknown method called
> QueryInterface that returns a pointer to ISomeInterface like
> so:

> class SomeInterfaceImpl : public ISomeInterface
> {
>      void QueryInterface(REFIID riid, void** ppv)
>      {
>          *ppv = static_cast<ISomeInterface*>(this);

If the lvalue which *ppv designates does not have the type
void*, this is undefined behavior.  You've lied to the compiler,
and the compiler has the right to punish you for it.

I am aware of implementations where a void* would be larger than
an ISomeInterface*.  On such an implementation, Assuming that
ppv was initialized (indirectly) with the reinterpret_cast in
your call above, this line will write not just isi, but also
some bytes behind it.  More generally, it will convert the
ISomeInterface* results of the cast to a void*, doing whatever
conversion is relevant for your machine, and then write the
results, as a void*, starting at the address of isi.  If (as is
usually the case), void* and ISomeInterface* have the same size
and representation, everything will work fine; if they don't,
you're screwed.

About the only way to write this line in a way that is
guaranteed to work according to the C++ standard would be to
declare the parameter of CoCreateInstance to be a void* (which
eliminates the need of a cast when calling it), and then write:
    *static_cast< ISomeInterface** >( ppv ) = this ;
here. Given the current interface, you need two pointers:
    void *          visi ;
    ISomeInterface* isi ;
You then pass &visi to CoCreateInstance, and the above line is
valid.  Later, when you want to use isi, you must static_cast
visi to ISomeInterface* and assign it to isi.

> 	reinterpret_cast<IUnknown*>(*ppv)->AddRef();

Same problem as above.  Except that this will actually fail,
even on a PC, if multiple inheritance is involved.  Even
assuming that all pointers have the same representation (which
the interface seems to do), the only valid reinterpret_cast of
*ppv is to the type of pointer that was actually stored there,
in this case, an ISomeInterface*.

>      }
>
>      // remaining implementations elided for clarity
> };

> Have the proper casts been used in the above code?  Can you
> explain why reinterpret_cast is needed in places where its
> been used?

What does Microsoft say about it?  There are definitly
architectures where this reinterpret_cast will NOT work, and
where it will get you into deep trouble.  But what it actually
does is somewhere between implementation defined and undefined
behavior.  If Microsoft says that it will work in this case,
then they are defining a legal extension to the language.  If
you're using COM, you're using extensions to the language
anyway, and your code won't work on a lot of platforms.
Anything regarding the use of COM is Microsoft's call, not that
of the C++ standard.  (The use of such techniques probably means
that COM cannot be implemented on a platform where void* and
SomeClass* have different representations.  But presumably, that
is a limitation that Microsoft is willing to take.)

--
James Kanze                                           GABI Software
Conseils en informatique orient�e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply kanze 9/7/2006 1:52:46 PM

Dilip wrote:
>
> ISomeInterface* isi;
> CoCreateInstance(......,...., reinterpret_cast<void**>(&isi));
>

I believe you need more than the Standard guarantees for this to work.
A more conformant way would be

  void* out_param;
  CoCreateInstance(......,...., &out_param);
  if (/* co-create succeeded */)
  {
    ISomeInterface* isi = static_cast<ISomeInterface*>(out_param);
    // code using isi here
  }

It also means you can't accidentally forget the & operator.

> Internally a lot of hocus-pocus happens and the API ends up calling an
> implementation of a standard IUnknown method called QueryInterface that
> returns a pointer to ISomeInterface like so:
>
> class SomeInterfaceImpl : public ISomeInterface
> {
>      void QueryInterface(REFIID riid, void** ppv)
>      {
>          *ppv = static_cast<ISomeInterface*>(this);
>
> 	reinterpret_cast<IUnknown*>(*ppv)->AddRef();
>      }
>
>      // remaining implementations elided for clarity
> };
>

Don't all interfaces inherit IUnknown? If so, the reinterpret_cast
isn't needed at all (or a static_cast could be used just in case AddRef
has been hidden by ISomeInterface).

What I've said only addresses the casts used in a COM-like system. If I
remember correctly, to create real COM classes in C++, the compiler
needs to lay out the objects in a particular way. I've mostly seen
C-style casts in COM code; these work because of the extra requirements
COM places on the compiler's ABI. (You can create COM classes on other
compilers, but COM features won't map to C++ features. For example,
you'd have to create your own v-tables - that's how you write COM
classes in C).

James


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply James 9/7/2006 1:53:19 PM

In article <1157561346.564859.260040@p79g2000cwp.googlegroups.com>, 
peter koch larsen <peter.koch.larsen@gmail.com> writes
>bjarne wrote:
>[SNIP]
>> Also, when you use static_cast, you stay within the semantics of the
>> language; when you use reinterpret_cast, you play with bits (the
>> representation). By doing static_cast<int*>(pv) when pv is a void*, you
>> assume that a void* is represented in exactly the same ways as an int*.
>>  That's by far the most common, but not guaranted.
>
>This statement scares me somewhat, but hopefully its just my
>understanding of english that suffers. static_casting from e.g. void*
>to int* can only be performed when the representation for void* is the
>same as for int* - and there is nothing that guarantees that this will
>work?  So - by inference - malloc is not guaranteed to work?
>I surely must misunderstand something - and yet I am the only one to
>react (so far!).


I suspect that under time pressure Bjarne has once again written 
static_cast when he intended reinterpret_cast.


-- 
Francis Glassborow      ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions:
http://www.spellen.org/youcandoit/projects


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Francis 9/7/2006 2:28:14 PM

kanze wrote:
> peter koch larsen wrote:
> > bjarne wrote:
> > [SNIP]
> > > Also, when you use static_cast, you stay within the
> > > semantics of the language; when you use reinterpret_cast,
> > > you play with bits (the representation). By doing
> > > static_cast<int*>(pv) when pv is a void*, you assume that a
> > > void* is represented in exactly the same ways as an int*.
> > > That's by far the most common, but not guaranted.
>
> > This statement scares me somewhat, but hopefully its just my
> > understanding of english that suffers. static_casting from
> > e.g. void* to int* can only be performed when the
> > representation for void* is the same as for int* - and there
> > is nothing that guarantees that this will work?  So - by
> > inference - malloc is not guaranteed to work?  I surely must
> > misunderstand something - and yet I am the only one to react
> > (so far!).
>
> I think that there was a type here as well, and that Bjarne was
> in fact talking about reinterpret_cast.  (Technically, the
> mapping done by reinterpret_cast is implementation defined, and
> an implementation could make it work here regardless.  But the
> statement "you play with bits" is, I think, an accurate informal
> description of the intent of reinterpret_cast.)

Okay - that was my original thought as well. I believe we can summarize
now that for a conversion from void* to e.g. int*, you must use
static_cast in order to be portable. This means I'll have to revise
some code - as I also used reinterpret_cast to do that trick (perhaps
inspired by bjarne as I used his books to learn C++ about 12 years
ago).

/Peter


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply peter 9/7/2006 6:28:17 PM

peter koch larsen wrote:
> bjarne wrote:
> [SNIP]
> > Also, when you use static_cast, you stay within the semantics of the
> > language; when you use reinterpret_cast, you play with bits (the
> > representation).

So far so good.

> > By doing static_cast<int*>(pv) when pv is a void*, you
> > assume that a void* is represented in exactly the same ways as an int*.
> >  That's by far the most common, but not guaranted.

Another typo. Sorry. I must stop posting while I'm drinking my first
cup of morning coffee (though when else do I find time?):

        I meant *reinterpret_cast* in that statement.

Static_casts don't mess with representations, so your are protected
from all representation-related problems (though, as with every cast
there are some potential problems, or you wouldn't need a cast) whereas
reinterpret_casts do.

The point was exactly that *reinterpret_cast* simply reinterprets the
representation so that you are making assumptions about the
representation of both the type you cast from and the type you cast to.
Most people are a bit vague about what is and what is not guaranteed by
the language.


> This statement scares me somewhat, but hopefully its just my
> understanding of english that suffers. static_casting from e.g. void*
> to int* can only be performed when the representation for void* is the
> same as for int* - and there is nothing that guarantees that this will
> work?  So - by inference - malloc is not guaranteed to work?
> I surely must misunderstand something - and yet I am the only one to
> react (so far!).
>
> /Peter
>

It was meant to scare you about *reinterpret_cast*. Reinterpret_cast
really is scary.

Use static_cast for malloc and you are as safe as you can ever be with
malloc().

   -- Bjarne Stroustrup; http://www.research.att.com/~bs


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply bjarne 9/7/2006 6:44:53 PM

bjarne wrote:

> Static_casts don't mess with representations, so your are
> protected from all representation-related problems (though, as
> with every cast there are some potential problems, or you
> wouldn't need a cast) whereas reinterpret_casts do.

Still on that first cup of coffee, or have I misunderstood
something?  A static_cast is almost required to modify the
representation in certain cases, and it is these modifications
which protect you, and make it work.  Whereas on a normal
machine, provided the implementation respects the intent of the
standard, a reinterpret_cast will never change the
representation; the bits in the pointer stay the same,
regardless.

> The point was exactly that *reinterpret_cast* simply
> reinterprets the representation so that you are making
> assumptions about the representation of both the type you cast
> from and the type you cast to.  Most people are a bit vague
> about what is and what is not guaranteed by the language.

My impression is that the standard itself is a bit vague about
what is guaranteed by reinterpret_cast.  Intentionally, so that
an implementation can make it do something useful (and
"unsurprising to those who know the addressing structure of the
underlying machine") regardless of how bizarre the architecture.

--
James Kanze                                           GABI Software
Conseils en informatique orient�e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply kanze 9/8/2006 4:16:20 PM

kanze wrote:

> bjarne wrote:
> 
>> Static_casts don't mess with representations, so your are
>> protected from all representation-related problems (though, as
>> with every cast there are some potential problems, or you
>> wouldn't need a cast) whereas reinterpret_casts do.
> 
> Still on that first cup of coffee, or have I misunderstood
> something?  A static_cast is almost required to modify the
> representation in certain cases, and it is these modifications
> which protect you, and make it work.  Whereas on a normal
> machine, provided the implementation respects the intent of the
> standard, a reinterpret_cast will never change the
> representation; the bits in the pointer stay the same,
> regardless.

I read "Static_casts don't mess with representations" as "Static_casts
are not defined in terms of representation", hence on a conceptual
level they have nothing to do with representations, and so you (the
programmer) don't have to worry about them.

A static_cast converts a pointer of some type A pointing to an object
x into a pointer of some type B pointing to the same object x.
It "messes with" the type of the pointer, not with anything else. As
you say, the representation may or may not have to be changed
depending on the situation and the platform, but that is all taken
care of by the compiler, and is "under the hood" of the abstraction
provided by static_cast.

Lourens


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Lourens 9/9/2006 7:09:15 PM

kanze wrote:
> bjarne wrote:
> 
>> Static_casts don't mess with representations, so your are
>> protected from all representation-related problems (though, as
>> with every cast there are some potential problems, or you
>> wouldn't need a cast) whereas reinterpret_casts do.
> 
> Still on that first cup of coffee, or have I misunderstood
> something?  A static_cast is almost required to modify the
> representation in certain cases, and it is these modifications
> which protect you, and make it work.  Whereas on a normal
> machine, provided the implementation respects the intent of the
> standard, a reinterpret_cast will never change the
> representation; the bits in the pointer stay the same,
> regardless.

I think it's a terminology thing; static_cast is defined
in terms of _values_, not representations, whereas in
most cases reinterpret_cast is implemented as identity
of _representations_ (though, as you said, the standard
doesn't require much of reinterpret_cast, and only alludes
indirectly to it not affecting representations).

-- James

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply James 9/9/2006 8:09:35 PM

In article <8e1a2$45027798$8259a2fa$27801@news1.tudelft.nl>, Lourens
Veen <lourens@rainbowdesert.net> writes
>A static_cast converts a pointer of some type A pointing to an object
>x into a pointer of some type B pointing to the same object x.
>It "messes with" the type of the pointer, not with anything else. As
>you say, the representation may or may not have to be changed
>depending on the situation and the platform, but that is all taken
>care of by the compiler, and is "under the hood" of the abstraction
>provided by static_cast.

No, not exactly true. If a class has multiple bases, a static cast can
be used to point to any of the base class objects and those will not all
share an address with the complete object.

-- 
Francis Glassborow      ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: 
http://www.spellen.org/youcandoit/projects


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Francis 9/9/2006 10:11:29 PM

{ Quoted clc++m banner removed. -mod }

kanze wrote:
> bjarne wrote:
>
> > Static_casts don't mess with representations, so your are
> > protected from all representation-related problems (though, as
> > with every cast there are some potential problems, or you
> > wouldn't need a cast) whereas reinterpret_casts do.
>
> Still on that first cup of coffee, or have I misunderstood
> something?  A static_cast is almost required to modify the
> representation in certain cases, and it is these modifications
> which protect you, and make it work.  Whereas on a normal
> machine, provided the implementation respects the intent of the
> standard, a reinterpret_cast will never change the
> representation; the bits in the pointer stay the same,
> regardless.

No, not the coffee (or lack thereof) this time :-)

I guess I should have said that reinterpret_cast "messes with the
meaning of representations" (rather than just "messing with
repesentations").  Static_cast manipulates values according to the type
rules of the language. Reinterpret cast does not. Consider:

    int main()
    {
        int i = 2;
        int* pi = &i;
        double* dp = reinterpret_cast<double*>(pi);
    }

The value of *dp is quite unlikely to be 2.0.


> > The point was exactly that *reinterpret_cast* simply
> > reinterprets the representation so that you are making
> > assumptions about the representation of both the type you cast
> > from and the type you cast to.  Most people are a bit vague
> > about what is and what is not guaranteed by the language.
>
> My impression is that the standard itself is a bit vague about
> what is guaranteed by reinterpret_cast.  Intentionally, so that
> an implementation can make it do something useful (and
> "unsurprising to those who know the addressing structure of the
> underlying machine") regardless of how bizarre the architecture.

Exactly. Reinterpret_casts is what you use as a last resort, making
assumptions about the machine. You can get into trouble with
static_cast (as with all cast), but reinterpret_cast is provided for
the cases where the compiler can provide essentially no help. An
experienced programmer may till be able to do something useful based on
knowledge of the machine.

   -- Bjarne Stroustrup; http://www.research.att.com/~bs


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply bjarne 9/10/2006 12:55:27 AM

Francis Glassborow wrote:
> In article <8e1a2$45027798$8259a2fa$27801@news1.tudelft.nl>, Lourens
> Veen <lourens@rainbowdesert.net> writes
>> A static_cast converts a pointer of some type A pointing to an object
>> x into a pointer of some type B pointing to the same object x.
>> It "messes with" the type of the pointer, not with anything else. As
>> you say, the representation may or may not have to be changed
>> depending on the situation and the platform, but that is all taken
>> care of by the compiler, and is "under the hood" of the abstraction
>> provided by static_cast.
> 
> No, not exactly true. If a class has multiple bases, a static cast can
> be used to point to any of the base class objects and those will not all
> share an address with the complete object.
> 

I believe that is consistent with the latter part of the
post to which you were replying, which did say

  > the representation may or may not have to be changed
  > depending on the situation and the platform, but that
  > is all taken care of by the compiler, and is "under
  > the hood" of the abstraction provided by static_cast

However, the sentence

  > It "messes with" the type of the pointer, not with anything else.

was somewhat unfortunate, and more descriptive of typical
implementations of reinterpret_cast than of static_cast.

-- James

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply James 9/10/2006 10:32:41 AM

Francis Glassborow wrote:

> In article <8e1a2$45027798$8259a2fa$27801@news1.tudelft.nl>, Lourens
> Veen <lourens@rainbowdesert.net> writes
>>A static_cast converts a pointer of some type A pointing to an
>>object x into a pointer of some type B pointing to the same object
>>x. It "messes with" the type of the pointer, not with anything else.
>>As you say, the representation may or may not have to be changed
>>depending on the situation and the platform, but that is all taken
>>care of by the compiler, and is "under the hood" of the abstraction
>>provided by static_cast.
> 
> No, not exactly true. If a class has multiple bases, a static cast
> can be used to point to any of the base class objects and those will
> not all share an address with the complete object.

I was considering them all to be the same object, but I'm not sure
whether that is accepted terminology. I think that we need to make a
clear distinction between the value of a variable and its
representation. Consider

struct A { /* ... */ }
struct B { /* ... */ }
struct C : public A, public B { /* ... */ }

int main() {
     C c;
     C * cp = &c;
     A * ap = static_cast<A *>(&c);
     B * bp = static_cast<B *>(&c);
}

If I call a member function on c through cp that modifies some
variable in the B subobject of c, then I will be able to see that
change through bp. So, conceptually, I'd argue that all the pointers
point to the same object.

In other words, the result of static_cast<B *>(&c) is a pointer of
type B * that points to c. The only difference between &c and
static_cast<B *>(&c) is that the type of the first expression is C *,
and the type of the second expression is B *. Their _value_ is the
same, namely "pointer to c", their types are different.

Now, most (all?) machines represent pointers as memory addresses. The
exact mapping between a pointer value and its representation depends
on the type of the pointer value and the type of the object it points
to. Depending on the compiler and the machine, bp may well have to
have a different representation than cp, even though they point to
the same object c (e.g. so that it stores the address of the
subobject of c of type B). So, static_cast may have to return a
different representation to ascertain that it returns the same value,
depending on the types it's casting from and to.

The language doesn't say anything about what the representation for &c
looks like however, and it doesn't specify whether static_cast
changes the representation or not. All it guarantees is that the
value remains the same, so that you can safely access c through bp.

Mr. Stroustrup expressed that (somewhat imprecisely) as "Static_casts
don't mess with representations". Perhaps "Static_casts don't deal
with representations, only with types and values. An implementation
of static_cast may change the representation to satisfy the
constraints on the value." would be a better description.

Lourens


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Lourens 9/10/2006 10:36:49 AM

In article <c4dea$4503d67b$8259a2fa$5933@news2.tudelft.nl>, Lourens Veen
<lourens@rainbowdesert.net> writes
>struct A { /* ... */ }
>struct B { /* ... */ }
>struct C : public A, public B { /* ... */ }
>
>int main() {
>     C c;
>     C * cp = &c;
>     A * ap = static_cast<A *>(&c);
>     B * bp = static_cast<B *>(&c);
>}
>
>If I call a member function on c through cp that modifies some
>variable in the B subobject of c, then I will be able to see that
>change through bp. So, conceptually, I'd argue that all the pointers
>point to the same object.
>
>In other words, the result of static_cast<B *>(&c) is a pointer of
>type B * that points to c. The only difference between &c and
>static_cast<B *>(&c) is that the type of the first expression is C *,
>and the type of the second expression is B *. Their _value_ is the
>same, namely "pointer to c", their types are different.


Sorry, IMHO that way madness lies. bp is a pointer to some B object or
subobject. The above code initialises it to a subobject of c. But we can
latter change it to point to some other B object. It does not inherently
point into a C object.

At best, after the initialisation above we can say that bp points into
c. Note that I can make the problem even more severe by using a virtual
base class.

-- 
Francis Glassborow      ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: 
http://www.spellen.org/youcandoit/projects


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Francis 9/10/2006 2:57:22 PM

Francis Glassborow wrote:

> In article <c4dea$4503d67b$8259a2fa$5933@news2.tudelft.nl>, Lourens
> Veen <lourens@rainbowdesert.net> writes
>>struct A { /* ... */ }
>>struct B { /* ... */ }
>>struct C : public A, public B { /* ... */ }
>>
>>int main() {
>>     C c;
>>     C * cp = &c;
>>     A * ap = static_cast<A *>(&c);
>>     B * bp = static_cast<B *>(&c);
>>}
>>
>>If I call a member function on c through cp that modifies some
>>variable in the B subobject of c, then I will be able to see that
>>change through bp. So, conceptually, I'd argue that all the pointers
>>point to the same object.
>>
>>In other words, the result of static_cast<B *>(&c) is a pointer of
>>type B * that points to c. The only difference between &c and
>>static_cast<B *>(&c) is that the type of the first expression is C
>>*, and the type of the second expression is B *. Their _value_ is
>>the same, namely "pointer to c", their types are different.
> 
> 
> Sorry, IMHO that way madness lies. bp is a pointer to some B object
> or subobject. The above code initialises it to a subobject of c. But
> we can latter change it to point to some other B object. It does not
> inherently point into a C object.

Maybe I'm mad then :). For what it's worth:

C is derived from B, so every C is a B. Hence c is a B, and bp can
point to it. If it does, bp probably won't hold the address of c but
some address inside c, but that doesn't make a difference
conceptually.

I know that C++ inheritance is not a strict type/subtype relationship
and that it violates the Liskov substitution principle, but I don't
think the idea is that outlandish.

Also, if B defined a virtual member function B::f() that was
overridden by C, how would you explain C::f() being called by bp->f()
if bp is pointing to a B subobject and doesn't know anything about
the C object that that B subobject it points to is part of?

I don't disagree with you that the address contained in bp may be
different from that contained in cp. It makes sense to implement it
that way and most if not all compilers do that. The problem is, we're
thinking on different levels. I'm talking about abstract concepts,
while you are talking about how they are implemented. The whole point
of static_cast over reinterpret_cast is that static_cast is defined
on that conceptual level, while reinterpret_cast requires knowledge
of implementation detail. That makes static_cast less dangerous than
reinterpret_cast.

Lourens


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Lourens 9/10/2006 6:13:31 PM

Francis Glassborow wrote:
> In article <c4dea$4503d67b$8259a2fa$5933@news2.tudelft.nl>, Lourens Veen
> <lourens@rainbowdesert.net> writes
> >struct A { /* ... */ }
> >struct B { /* ... */ }
> >struct C : public A, public B { /* ... */ }
> >
> >int main() {
> >     C c;
> >     C * cp = &c;
> >     A * ap = static_cast<A *>(&c);
> >     B * bp = static_cast<B *>(&c);
> >}

<snip>

> >In other words, the result of static_cast<B *>(&c) is a pointer of
> >type B * that points to c. The only difference between &c and
> >static_cast<B *>(&c) is that the type of the first expression is C *,
> >and the type of the second expression is B *. Their _value_ is the
> >same, namely "pointer to c", their types are different.
>
>
> Sorry, IMHO that way madness lies. bp is a pointer to some B object or
> subobject. The above code initialises it to a subobject of c. But we can
> latter change it to point to some other B object. It does not inherently
> point into a C object.
>
> At best, after the initialisation above we can say that bp points into
> c. Note that I can make the problem even more severe by using a virtual
> base class.
>

I think it depends on the style of the code. If B was designed as a
polymorphic base class (or interface), surely the only valid way to
think of bp is that it 'points to c'. I think the normal way of writing
the code:

   B* bp = &c;

says that pretty clearly.

It does rely on B and C conforming to OO conventions, and of course
there are other ways of using inheritance in C++, such as
implementation (boost::iterator_facade is my favourite example). In
those cases, though, you wouldn't normally have a pointer or reference
to base in client code. The base is just an implementation detail (and
the compiler-provided conversion unfortunate, but not a problem in
practice).


James


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply James 9/11/2006 1:34:37 PM

kanze wrote:
> Diego Martins wrote:
>
> > But it is WRONG to use reinterpret_cast in this example?
> > In my programs, I use reinterpret_cast to cast to void * and cast back
> > to the original pointer type.
> > Are there any drawbacks using this approach? What does static_cast buy
> > me in this case?
>
> It sends the wrong message to the reader.
>
> When I see a reinterpret_cast in code, I immediately assume that
> there is something very delicate and implementation dependant
> going on.  When I see a static_cast, I suppose that while you
> are subverting the type system somewhat, it is within more
> reasonable bounds, and is portable---I don't have to pay
> particular attention to it when porting to another system, for
> example.
>
Whenever I see a reinterpret cast in our code, I know someone is doing
a tremendous hack. I've come accross places where 5 consecutive lines
of code with 3 reinterpret_cast's in them. A little thought would have
eliminated all 3 of them.

There are times when I wish the standards comittee had called
reinterpret_cast something more thought provoking, like (say)
I_understand_what_I_am_doing_is_actually_a_tremendous_hack_and_is_unlikely_to_work_if_almost_anything_changes_cast

and banned C-style casts entirely


It seems to be all to easy to write reinterpret_cast rather thank
applying the gray matter.


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply ThosRTanner 9/12/2006 10:42:54 AM

ThosRTanner wrote:

> Whenever I see a reinterpret cast in our code, I know someone is doing
> a tremendous hack. I've come accross places where 5 consecutive lines
> of code with 3 reinterpret_cast's in them. A little thought would have
> eliminated all 3 of them.
>
> There are times when I wish the standards comittee had called
> reinterpret_cast something more thought provoking, like (say)
>
I_understand_what_I_am_doing_is_actually_a_tremendous_hack_and_is_unlikely_t
o_work_if_almost_anything_changes_cast

:-) "reinterpret_cast" is already pretty long/LOUD compared to the
average C++ keyword.


> and banned C-style casts entirely

I proposed deprecation of C-style casts, but I could not get consensus
for that in the committee.


> It seems to be all to easy to write reinterpret_cast rather thank
> applying the gray matter.

and even easier to write a C-style cast.

  -- Bjarne Stroustrup; http://www.research.att.com/~bs


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply bjarne 9/12/2006 6:25:51 PM

bjarne wrote:
> I proposed deprecation of C-style casts, but I could not get consensus
> for that in the committee.

Isn't a C-style cast appropriate for casting integer types:

long long a = 1;
int b = (int)a;
short c = (short)b;


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply andrew_nuss 9/12/2006 9:13:44 PM

"andrew_nuss@yahoo.com" <andrew_nuss@yahoo.com> writes:

| bjarne wrote:
| > I proposed deprecation of C-style casts, but I could not get consensus
| > for that in the committee.
| 
| Isn't a C-style cast appropriate for casting integer types:
| 
| long long a = 1;
| int b = (int)a;
| short c = (short)b;

yes, but you would do the same with a less catch-all syntax.

Notice that, in C++, the semantics of C-style cast is defined in terms of
those of new-style casts.

-- 
                                                       Gabriel Dos Reis 
                                           gdr@integrable-solutions.net

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Gabriel 9/12/2006 11:26:24 PM

andrew_nuss@yahoo.com posted:

> Isn't a C-style cast appropriate for casting integer types:
> 
> long long a = 1;
> int b = (int)a;
> short c = (short)b;


I would agree on this point, I commonly do such things as:

    unsigned i = (char unsigned)-1;

-- 

Frederick Gotham

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Frederick 9/12/2006 11:27:00 PM

andrew_nuss@yahoo.com skrev:
> Isn't a C-style cast appropriate for casting integer types:
> 
> long long a = 1;
> int b = (int)a;
> short c = (short)b;
> 

I don't know about you, but I would have written:

long long a = 1;
int b = a;
short c = b;

or,

long long a = 1;
int b(a);
short c(b);

or,

long long a = 1;
int b = int(a);
short c = short(b);

I don't think there is anything I would miss if the C style cast where gone.

-----
Bj�rn Roald

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply ISO 9/12/2006 11:48:29 PM

Bj�rn Roald posted:

> I don't know about you, but I would have written:
>
> long long a = 1;
> int b = a;
> short c = b;


You'll get compiler warnings.


> or,
>
> long long a = 1;
> int b(a);
> short c(b);


Again, you'll get compiler warnings.



> or,
>
> long long a = 1;
> int b = int(a);
> short c = short(b);


Those directly above are C-style casts -- they're just dressed up to look
pretty.

--

Frederick Gotham

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Frederick 9/13/2006 3:50:29 AM

Frederick Gotham skrev:
> Bj�rn Roald posted:
>
>> I don't know about you, but I would have written:
>>
>> long long a = 1;
>> int b = a;
>> short c = b;
>
>
> You'll get compiler warnings.
>
>
>> or,
>>
>> long long a = 1;
>> int b(a);
>> short c(b);
>
>
> Again, you'll get compiler warnings.
>

May very well be true that you get warnings on some compilers, but:

#include <iostream>
int main()
{
    long long a = 1;
    std::cout << "Enter a (long long) number: ";
    std::cin >> a;
    if( std::cin )
    {
      int b = (int)a;
      short c = (short)b;

      int bb = a;
      short cc = b;

      int bbb = int(a);
      short ccc = short(b);

      int bbbb(a);
      short cccc(b);

      int bbbbb = static_cast<int>(a);
      short ccccc = static_cast<short>(b);

      std::cout << a << ' '
                << b <<  ' '
                << c <<  ' '
                << bb <<  ' '
                << cc <<  ' '
                << bbb <<  ' '
                << ccc <<  ' '
                << bbbb <<  ' '
                << cccc <<  ' '
                << bbbbb <<  ' '
                << ccccc <<  '\n';
    }
    else
    {
      std::cout << std::endl <<
        "are you sure that was a long long integer?" << std::endl;
    }
    return 0;
}

compiled like this:

   g++ -Wall    casts.cpp   -o casts

produces no warnings.


My concern however (and you cut out some context here) is whether this
is not equally or more appropriate for the obviously intended result
than C-style casts.  I fail to see how the compiler can help you any
more with a C-style cast.  Hence the only thing you archive with C-style
cast here is to disable your compilers chance to warn you, you tell it
to trust you.  And you are doing it in a way that is hard to spot for
readers of your code or simple tools. Sometimes that warning may come in
handy to people including yourselves dealing with the code later.

On the other hand, since tools like g++ produce no warning.  Then a very
clear way to declare the cast in the code is to use static_cast.  E.g.
if you are looking through code for potential trouble spots, then you
could search for '_cast', have you ever tried to search for C-style
casts, or any of those other implicit casts I suggested above.

>
>
>> or,
>>
>> long long a = 1;
>> int b = int(a);
>> short c = short(b);
>
>
> Those directly above are C-style casts -- they're just dressed up to look
> pretty.

I like the look of them better, yes :-).  If removing C-style cast from
the standard in the distant future would take these away, then I think I
   would miss this feature a bit.


---
Bj�rn Roald

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply ISO 9/13/2006 1:36:49 PM

In article <rtGNg.13647$j7.330054@news.indigo.ie>, Frederick Gotham
<fgothamNO@SPAM.com> writes
>andrew_nuss@yahoo.com posted:
>
>> Isn't a C-style cast appropriate for casting integer types:
>>
>> long long a = 1;
>> int b = (int)a;
>> short c = (short)b;
>
>
>I would agree on this point, I commonly do such things as:
>
>    unsigned i = (char unsigned)-1;

The only reason I would consider this is for C compatibility. However I
must confess there is a single exception in my style, I happily use and
advocate the use of a function style cast (OK not quite a c-style cast)
for converting the value of an expression to an enum.

enum color {black, red, green, blue, white = 7};

color c;
c = color(red + green);



--
Francis Glassborow      ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Francis 9/13/2006 1:41:05 PM

andrew_nuss@yahoo.com wrote:
> bjarne wrote:
> > I proposed deprecation of C-style casts, but I could not get
> > consensus for that in the committee.

> Isn't a C-style cast appropriate for casting integer types:

> long long a = 1;
> int b = (int)a;
> short c = (short)b;

Well, it's always a question of style, but... there are three
types of casts in C++: the "new" style, functional style, and
the old C style.  I don't see any problem in using the
functional style when the intent is clearly to create a new
object:

    f( MyClass( a ) ) ;

; in addition, they are the only type which works if the number
of arguments needed to create the new object isn't exactly 1.

(For that reason, I'd much rather see them called something else
in the standard, like "explicit creation of a temporary".  And
also that such an expression wouldn't use a user defined
conversion operator---I suspect that most people would be
surprised if this expression called a.operator MyClass(), which
it can.)

Given that, I'd also write (or prefer to see):

    long long a = 1 ;
    int b = (long long)( a ) ;
{{ the poster most likely intended "int b = int( a ) ;"  -mod }}
    short c = short( b ) ;
            //  or (short)( b )...

Formally, as soon as the typename is in parentheses (and if the
typename requires more than one symbol, it must be in
parentheses), we have a C style cast, and not a function style
cast.  But I think that in terms of what the reader understands:
as soon as what is being converted is in parentheses, I see the
explicit creation of a temporary.  (But maybe that's just me.)

And I would never accept such conversions where pointers or
references were involved (even though technically, a pointer is
an object, and you can create a temporary which has a pointer
type just like you can create any other temporary).

Given the ambiguities that the function style cast creates, it
would probably have been better to have only the new style cast,
and an "explicit creation of a temporary" expression, in which
the type of the temporary must be in parentheses, but in which
the number (and type) of parameters must correspond to an
available constructor (and of course, all of the available
constructors for int take a single parameter).  But of course,
it's too late for that now, and given the historical context, I
don't see how anyone could have had the idea when it would have
been possible.

--
James Kanze                                           GABI Software
Conseils en informatique orient�e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply kanze 9/13/2006 4:06:39 PM

ThosRTanner wrote:
>
> It seems to be all to easy to write reinterpret_cast rather thank
> applying the gray matter.
>

Can someone help me with the gray matter here?
I am using anti-bloat techniques with arrays of pointers in a template
class.
What I need to do is equivalent to the following intent:

void** vbase = ...;
int** ibase = some_cast<int**>(vbase);

What cast am I supposed to use in view of the above.  Are these
compatible
types for a static_cast?

-Andy


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply andrew_nuss 9/13/2006 4:08:56 PM

{ this is a clarification of an earlier post, it seems.  if you happen
  to be still thinking how to answer the first one, perhaps you should
  reply to this one instead.  thanks!  -mod }

I have a question that relates to the original topic of whether there
is a good case for reinterpret_cast.

In my anti-bloat template for an Array<T>, I detect when T is a pointer
and use a void** to hold the base of the array.  The problem is that my
operator[] needs to return a reference to T, rather than a pointer,
because I want to use ar[N] on both lhs and rhs.  The conundrum is
equivalent to the following snippet:

void** base = ...;
int index = ...;
int*& val = static_cast<int*&>(base[index]);   //illegal!!!

Note that the last line is the equivalent of what I want for an
operator [] that returns T&.  My guess is that both C-style casts and
reinterpret_casts "work" for the same reasons, but both are
undersirable according to this thread.  So what is the solution?

Andy


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply andrew_nuss 9/13/2006 4:30:22 PM

andrew_nuss@yahoo.com wrote:
> bjarne wrote:
> > I proposed deprecation of C-style casts, but I could not get consensus
> > for that in the committee.
>
> Isn't a C-style cast appropriate for casting integer types:
>
> long long a = 1;
> int b = (int)a;
> short c = (short)b;
>

Unfortunately, those casts are just comments: Remove them and you get
exactly the same results. What would be useful would be some way of
disabling narrowing conversions so that we could use casts only when
needed, and in that case, we'd like a choice of a checked and an
unchecked cast.

One proposal
(http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2006/n2100.pdf) is
to have a form of initialization that doesn't narrow:

   int b = {a};  // error: narrowing

another is to have some form of Boost's lexical cast:

  int b = lexical_cast<int>(a);  // throw if the value of a doesn't fit
in b.

  -- Bjarne Stroustrup; http://www.research.att.com/~bs


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply bjarne 9/13/2006 6:33:04 PM

Francis Glassborow wrote:
> In article <rtGNg.13647$j7.330054@news.indigo.ie>, Frederick Gotham
> <fgothamNO@SPAM.com> writes
> >andrew_nuss@yahoo.com posted:
> >
> >> Isn't a C-style cast appropriate for casting integer types:
> >>
> >> long long a = 1;
> >> int b = (int)a;
> >> short c = (short)b;
> >
> >
> >I would agree on this point, I commonly do such things as:
> >
> >    unsigned i = (char unsigned)-1;
>
> The only reason I would consider this is for C compatibility. However I
> must confess there is a single exception in my style, I happily use and
> advocate the use of a function style cast (OK not quite a c-style cast)
> for converting the value of an expression to an enum.
>
> enum color {black, red, green, blue, white = 7};
>
> color c;
> c = color(red + green);

>From my point of view, function style casts are constructors.
That is the way I use them. No compiler warnings at all.

Diego


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Diego 9/13/2006 6:38:44 PM

On 13 Sep 2006 09:41:05 -0400, Francis Glassborow
<francis@robinton.demon.co.uk> wrote:

>>I would agree on this point, I commonly do such things as:
>>
>>    unsigned i = (char unsigned)-1;
>
>The only reason I would consider this is for C compatibility.

I agree 100%. For when I need a constant expression (so that
numeric_limits<>::max() cannot help) I have my own metafunctions
max<T> and min<T>. Trivial to write and, to me, extremely useful.

On a side note, I think numeric_limits was very badly designed.

>However I must confess there is a single exception in my style,
>I happily use and advocate the use of a function style cast (OK
>not quite a c-style cast) for converting the value of an expression
>to an enum.
>
>enum color {black, red, green, blue, white = 7};
>
>color c;
>c = color(red + green);

Why that particular exception? BTW, from the code above I guess you
use a all-ones value at the end *which isn't part of the actually used
enumerators*. Otherwise you cannot do, for instance, white + blue (not
that it is particularly meaningful in this specific case :-)):

  enum color { black = 1, red, green, blue, white, all_colors = 16 };

I find the technique a bit fragile anyway, since if you add an
enumerator you must remember to update the value of all_colors (but
I'm just guessing about your intent here).

--
Gennaro Prota

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Gennaro 9/13/2006 6:41:52 PM

Gennaro Prota wrote:
> On 13 Sep 2006 09:41:05 -0400, Francis Glassborow
> <francis@robinton.demon.co.uk> wrote:

    [...]
> >enum color {black, red, green, blue, white = 7};

> >color c;
> >c = color(red + green);

> Why that particular exception?

Why not:-)?  But then, why not also for other non-lossy integral
conversions?

> BTW, from the code above I guess you use a all-ones value at
> the end *which isn't part of the actually used enumerators*.

I suspect rather that he just jumped at the first example which
came to mind where you might want to use the results of a binary
operation as the enum type, and didn't really think about any of
the details.  Off hand, I'd guess the actual example he had in
mind was more along the lines of:

    enum Color {
        black = 0,
        red   = 1,
        green = 2,
        blue  = 4,
        white = 7
    } ;
    Color c = Color( red | green ) ;

(In his example, he added red and green to get blue.  And I'm
sure Francis would never expect that to work in real life.)

I also suspect that in practice, the casts would only be used in
a user defined overloaded operator:

    Color
    operator|( Color lhs, Color rhs )
    {
        return Color( unsigned( lhs ) | unsigned( rhs ) ) ;
    }

And I wonder what type of cast he actually uses for the unsigned
in the above.  (In practice, I almost always forget the inner
casts the first time around.  I wonder if it would be too much
effort for a compiler to warn when a user defined operator uses
itself---I can't think of any case where recursion would make
sense for user defined operators.)

--
James Kanze                                           GABI Software
Conseils en informatique orient�e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply kanze 9/14/2006 12:11:23 PM

andrew_nuss@yahoo.com wrote:
> ThosRTanner wrote:

> > It seems to be all to easy to write reinterpret_cast rather
> > thank applying the gray matter.

> Can someone help me with the gray matter here?  I am using
> anti-bloat techniques with arrays of pointers in a template
> class.  What I need to do is equivalent to the following
> intent:

> void** vbase = ...;
> int** ibase = some_cast<int**>(vbase);

> What cast am I supposed to use in view of the above.

None.  A reinterpret_cast will get it through the compiler, but
the fact that only a reinterpret_cast works should tell you that
there's something wrong.  It won't work on some machines.
(Think about it for a moment.  Consider the case where
sizeof( void* ) != sizeof( int* ).)

> Are these compatible types for a static_cast?

No, because whether the conversion works or not depends on the
addressing architecture of the target platform.

--
James Kanze                                           GABI Software
Conseils en informatique orient�e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply kanze 9/14/2006 12:12:06 PM

andrew_nuss@yahoo.com wrote:

> I have a question that relates to the original topic of
> whether there is a good case for reinterpret_cast.

> In my anti-bloat template for an Array<T>, I detect when T is
> a pointer and use a void** to hold the base of the array.  The
> problem is that my operator[] needs to return a reference to
> T, rather than a pointer, because I want to use ar[N] on both
> lhs and rhs.  The conundrum is equivalent to the following
> snippet:

> void** base = ...;
> int index = ...;
> int*& val = static_cast<int*&>(base[index]);   //illegal!!!

> Note that the last line is the equivalent of what I want for
> an operator [] that returns T&.  My guess is that both C-style
> casts and reinterpret_casts "work" for the same reasons, but
> both are undersirable according to this thread.  So what is
> the solution?

Question: what is the reference supposed to designate in the
case where void* has a different representation than int*?

In practice, I'm pretty sure that it is safe to assume that a
void* is at least as big as any other pointer type, since you
can assign any other pointer type to it without loss of
information.  And I can't imagine a case where it has less
strict alignment requirements either.  In such cases, if *ALL*
reads and writes to the actual memory pass through the necessary
casts (reinterpret_cast's here, because you are lying like crazy
to the compiler), it should work.

Alternatively, you could use some sort of conditional
compilation, using the refactored versions only on machines
where all data pointer types have the same representation (which
covers a fair percentage of the machines on the market today).
Again, it's reinterpret_cast that you want here as well, because
the code definitly isn't portable, and you do have to consider
whether to use it or not each time you port to a new machine.
(In practice, this is the alternative I'd use, since it seems
safer to me---even if you slip up, and do access the void* at
some moment, say when copying, you're safe.)

--
James Kanze                                           GABI Software
Conseils en informatique orient�e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply kanze 9/14/2006 12:12:36 PM

andrew_nuss@yahoo.com wrote:

> In my anti-bloat template for an Array<T>, I detect when T is a
> pointer and use a void** to hold the base of the array.

Do you mean that basically Array has only code without binary mass, 
typesafely wrapping a single non-template raw storage holder for any 
T? If so, I presume the usual storage holder keeps a void* but now 
you want to use another holder for pointer types T. Why?

> void** base = ...;
> int index = ...;
> int*& val = static_cast<int*&>(base[index]);   //illegal!!!

What does the first line actually say?


Martin

-- 
Quidquid latine scriptum sit, altum viditur.

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Martin 9/15/2006 1:59:34 PM

Josef Svitak <jsvitak@gmail.com> wrote:
> andrew_nuss@yahoo.com wrote:
>> I've noticed that on pg. 342 of Stroustups "C++ Programming Language"
>> book his example of using partial specialization for a custom vector
>> template where T is a pointer to anything to avoid bloat, he uses
>> reinterpret_cast to go back and forth between void* and T* pointers.
>> Why?  Why not use static_cast?
> 
> This has been fixed in the "Special Edition" to use static_cast.

Well, in my version of the Special Edition (10th Printing, May 2004), it
still has reinterpret_cast.  I also did not see this change mentioned as
an errata item on Dr. Stroustrup's page, though I did see his note about
not posting errata items that don't "significantly affect a reader's
ability to comprehend".

-- 
Marcus Kwok
Replace 'invalid' with 'net' to reply

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply ricecake 9/15/2006 11:50:53 PM

bjarne wrote:

> > and banned C-style casts entirely
>
> I proposed deprecation of C-style casts, but I could not get consensus
> for that in the committee.
>
>
> > It seems to be all to easy to write reinterpret_cast rather thank
> > applying the gray matter.
>
> and even easier to write a C-style cast.

I have one argument for C-style casts. Consider following library code:

//NOTE: untested code
struct cast_helper_t
{
     cast_helper_t(std::string const& str) :
         m_str(str) {}

     template <typename T>
     operator T () const {
         // use stringstream to convert m_str to T
     }

private :
     std::string m_str;
};

template <typename T>
T from_string(std::string const& str)
{
     // use stringstream to convert str to T
}

cast_helper_t from_string(std::string const& str)
{
     return cast_helper_t(str);
}

Then user of this library can convert strings to numerical or UDT types
as in the following code:

int i = from_string("1");
// NOTE: cast is called implicitly

//int i = 1 + from_string("1");
// NOTE: won't compile, ambigous conversion (int or double)

int i = 1 + from_string<int>("1");
// NOTE: templated version is called
// translating to english:
// integer 'i' is a one plus 'obtained' from string integer from string
"1"
// bad english, but the aim is to reflect the parsing of this statment
by programmer

int i = 1 + static_cast<int>(from_string("1"));
// NOTE: 1) too verbose for everyday use; 2) static_cast suggests
design failure

int i = 1 + (int)from_string("1");
// NOTE: C-style cast calls the cast operator of cast_helper_t struct
// translating to english:
// integer 'i' is a one plus integer from string "1"
// much better. isn't it? At least my brain generated lesser amount of
entropy during reading it.

The problem is not in C-style cast here. The problem is - the lack of
language support to explicitly call user-supplied conversion operator
without syntactical overhead. I understand that this overhead is by
intention and it suggests that casts are evil, but what about this
particular case? Is this library defective by design because it can not
be used with pleasure without C-style casts?

or, maybe it is possible to provide some special syntax to allow such a
library to be usable, for example:
int i = 1 + <int>from_string("1");
// explicit call of user defined conversion operator and only that.
nothing else.

Oleg Abrosimov.


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Oleg 9/19/2006 5:15:14 PM

"Oleg" <beholder@gorodok.net> writes:

[...]

| int i = 1 + static_cast<int>(from_string("1"));
| // NOTE: 1) too verbose for everyday use; 2) static_cast suggests
| design failure
|
| int i = 1 + (int)from_string("1");
| // NOTE: C-style cast calls the cast operator of cast_helper_t struct
| // translating to english:
| // integer 'i' is a one plus integer from string "1"
| // much better. isn't it? At least my brain generated lesser amount of
| entropy during reading it.

To me, the static_cast syntax in your example does not suggest more
design failure than the C-style cast.  I read quite the opposite.

-- 
                                                       Gabriel Dos Reis
                                           gdr@integrable-solutions.net

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Gabriel 9/20/2006 4:34:12 PM
comp.lang.c++.moderated 10633 articles. 8 followers. Post

63 Replies
1259 Views

Similar Articles

[PageSpeed] 40


  • Permalink
  • submit to reddit
  • Email
  • Follow


Reply:

Similar Artilces:

new, reinterpret_cast<void*> and delete
Should 'delete below (after casting to void*)' work fine? ------------------------------------------ char* p1 = new (nothrow) char[100]; if (p1 == 0) return; void* p2 = reinterpret_cast<void*> (p1); delete p2; ------------------------------------------ Alex Vinokur email: alex DOT vinokur AT gmail DOT com http://mathforum.org/library/view/10978.html http://sourceforge.net/users/alexvn "Alex Vinokur" <alexvn@users.sourceforge.net> schrieb im Newsbeitrag = news:1143449992.138796.54260@v46g2000cwv.googlegroups.com... > Should 'delete below (...

To void or not to void
Normally, in C++ one doesn't use void in a function declaration when it takes no parameters. You need to in C. So what about a C++ function declared with an extern "C"? Example: extern "C" void __declspec(dllexport) functionName() // does this need to be (void)? As is probably evident, this is in a Windows DLL. Right now, the entire program is C++. I don't know if it will ever be used with C modules. Brian * Default User, on 14.03.2011 01:23: > Normally, in C++ one doesn't use void in a function declaration when it > takes no parameters. You n...

What is the difference between void proba(); and void proba(void); ???
What is the difference between void proba(); and void proba(void); ??? PencoOdStip@gmail.com wrote: > What is the difference between void proba(); and void proba(void); ??? None, as far as C++ language is concerned. As far as style, I don't like the latter. If there are no arguments, the parens should contain nothing. V -- Please remove capital 'A's when replying by e-mail I do not respond to top-posted replies, please don't ask ...

Does void f(); override void f(void);
Does the function: void f(); in a derived class, override void f(void); in the base class? It should do, but does it? I only asked. [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] Bill Reyn wrote: > Does the function: void f(); in a derived class, override void > f(void); in the base class? > It should do, but does it? They're the exact same. Note: - 'override' might not work as expected if the one in the base is not virtual - in C, 'void f()' mean a function with unspecif...

what is the difference, void func(void) and void fucn()
Hi all, What is the difference between following two function definations? <1> void func(void) { /* some code */ } <2> void func() { /* some code */ } Why would somebody use 2nd one? --santosh. noblesantosh@yahoo.com wrote: > Hi all, > What is the difference between following two function definations? > <1> > void func(void) > { > /* some code */ > } > > <2> > void func() > { > /* some code */ > } Both define a function returning void, and accepting zero arguments. They define `func' with different types. The first typ...

Casting void * to void ** ?
Hi All, I have a question which might sound very basic. I have a simple structure: struct simple{ void *buffer; }; typedef struct simple Simple; In my function I do this: void do_Something(){ Simple *simp_struct; simp_struct->buffer = malloc(10 * sizeof(int *)); call_func((void **)((int **)(simp_struct->buffer))); .... } The function call_func has this prototype: call_func(void **buf); I am confused with this piece of code: call_func((void **)((int **)(simp_struct->buffer))); What does this construct mean? How is that simp_struct->buffer (which is a void *) is...

`void **' revisited: void *pop(void **root)
Hi group, I'm playing with a little generic linked list/stack library, and have a little problem with the interface of the pop() function. If I used a struct like this it would be simple: struct node { struct node *next; void *data; }; Doing this requires at least two allocations per node. I want to get that down to 1. The program at the bottom of this post illustrates what I want to do: the declaration of `struct node2' would exist only in the library source file. When using the library I would be able to define multiple lists of different types of elements. The only requirement ...

void dummyfunction (void)
Why do you 'void' why? void dummyfunction (void) thanks Mike [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] "Mike" <mikedinh1234@hotmail.com> wrote in message news:ae1b7d0e.0311270841.23d8c56@posting.google.com... > Why do you 'void' why? > > void dummyfunction (void) The first because you dont return a value and the second because you want the same decl to work for C and C++. In C dummyfunction() means dummyfunction(...) in C++ dummyfunction() means dummyf...

returning a void (*)(void)
If I have a private member: void (*func)(void); how can i declare a 'get' function that returns it? I tryed: void (*)()GetFunc() { return func; } but looks like that's not the way... thanks On 5 Jan 2005 03:57:37 -0800, "Sergio" <sergiozin@gmail.com> wrote: >If I have a private member: > >void (*func)(void); > >how can i declare a 'get' function that returns it? I tryed: > >void (*)()GetFunc() >{ > return func; >} > >but looks like that's not the way... > >thanks It's easier with a typedef: typ...

void* and void** compatibility
Is void * and void ** is compatible? =20 I do not get any compiler warning or error message for the first two functi= ons (written below) but for the third one the compiler throws the following= warning=20 gcc -ansi -pedantic -Wall test.c test.c: In function =91TestChar=92: test.c:17:5: warning: return from incompatible pointer type #include<stdlib.h> void **TestVoid()=20 { void *p =3Dmalloc(2); return p; } void *TestVoid2()=20 { void **p =3Dmalloc(2); return p; } char **TestChar() { char *p =3D malloc(2); return p; } int main(...

void main(void)?
Hi, I've been creating some simple C++ (Carbon) projects to test code I need to add to existing projects. I just noticed that when I create a new "stationary", CodeWarrior writes "void main(void)" as the signature for the main function. Isn't main required (by the standard) to return an int? I've seen a lot of folks chastised on comp.lang.c++ for posting code with void main functions, but it's hard to blame the programmers when the tools produce (and compile!) what is supposedly llegal code. -Howard In article <s0oXc.518965$Gx4...

from 'void **' to void 'void const **'
Is there anything about the second level of indirection here that should make 'def = abc' inappropriate? void **abc; const void **def; void test(void) { def = abc; } Simon Hosie <gumboot@REM-taosstolt-OVEclear.net.nz> wrote in message news:<deooq1-lv2.ln1@bovine.muck.net.nz>... > Is there anything about the second level of indirection here that should > make 'def = abc' inappropriate? > > void **abc; > const void **def; > > void test(void) > { > def = abc; > } def points to a pointer to void qua...

"void Method()" vs "void Method(void)"
Hello, I would like to know if there is a difference in c++ between the following two method-declarations: void Method(); and void Method(void); I know there is a difference in C (the first case means the function may have parameters, but they are not yet defined?). But how is the semantik in C++? Is there a difference or are both declarations equal in _every_ case? I would be glad to get an answer to this question (and perhaps a reference where this topic is explained (C++-standard?)). Regards ollej "Ollej Reemt" <ollej@gmx.de> wrote in message news:d458o7$jk7@ne...

int main(void) Why void?
Hello everyone, I have noticed everyone using "int main(void)".But doesnt the standard pronounces it as "int main(int argc,char *argv[])".And if i don't specify arguments,why can't i simply put it as "int main()" Rahul rahulsinner@gmail.com schrieb: > I have noticed everyone using "int main(void)".But doesnt the > standard pronounces it as > "int main(int argc,char *argv[])".And if i don't specify arguments,why > can't i simply put it as "int main()" See FAQ 11.12a. As it is usually better to make...

why we require void func( void ** ) ?
Hi why we require void func( void ** ) ? Thanks Pallav Singh Pallav singh <singh.pallav@gmail.com> writes: > why we require void func( void ** ) ? What do you mean? Require it as opposed to what? -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Nokia "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" ...

Casting const void * into void *
Given: typedef struct Node Node; struct Node { void *obj; Node *next; }; typedef struct Stack Stack; struct Stack { Node *top; }; ....is the following a conforming C function (I am particularly worried about the casts), since I'm not modifying the obj parameter? void *stack_push(Stack *s, const void *obj) { Node *n; assert(s != NULL); assert(obj != NULL); n = malloc(sizeof *n); if (n == NULL) return NULL; /* push failed */ n->obj = (void *) o...

why we require void func( void ** ) ?
Hi why we require void func( void ** ) ? Thanks Pallav Singh -- comp.lang.c.moderated - moderation address: clcm@plethora.net -- you must have an appropriate newsgroups line in your header for your mail to be seen, or the newsgroup name in square brackets in the subject line. Sorry. Pallav singh <singh.pallav@gmail.com> writes: > why we require void func( void ** ) ? Did you think you'd get a different answer here than on comp.std.c? Your question doesn't make sense; you need to provide some context. DES -- Dag-Erling Smørgrav - des@des.no -...

method type void* (*) (void*)
I am getting task.cpp:109: error: argument of type 'void (Spac_task::)()' does not match 'void* (*)(void*)' when trying to execute the line int thr_id = pthread_create(&p_thread, NULL, spc_optm, NULL); where void Spac_task::spc_optm(){/*...*/} if I change it to void* Spac_task::spc_optm(void*){/*...*/} then I get task.cpp:109: error: argument of type 'void* (Spac_task::)(void*)' does not match 'void* (*)(void*)' I even tried static void* (*) spc_optm(void*); static void* (*) Spac_task::spc_optm(void*){/*...*/} that did not cu...

void
Hello! I think a void program would be useful. I haven't found one under the current unix-utils and I could not find a way to realize it by abusing some other unix-tool like 'echo'. What about [[[ // Program void. // Always succeed and ignore all arguments. int main() { return 0; } ]]] It ignores all arguments and always succeeds. What do you think? Best wishes -- Marco Wahl mw.visenso@googlemail.com wrote On 03/10/06 12:23,: > Hello! > > I think a void program would be useful. I haven't > found one under the current unix-utils and I could not > ...

void
test ...

reinterpret_cast
I am trying to understand reinterpret_cast,here is what i tried, #include<iostream> #include<cstdio> using namespace std; int main() { int x=1; int* y=&x; char* p= reinterpret_cast<char*>(y); /*I expect the following line to access different bytes of x as chars and print them.what should I expect?Am i expecting right? */ printf("\n the chars are %c %c %c %c\n",p[0],p[1],p[2],p[3]); return 0; } I want to know what is going behind. Thanks for any help. On Jun 10, 2:25=A0pm, saurabh <hah...@hehehe.com> wrote: > I am ...

void
What does (void) poService in followinf peace of code mean tclCtrlBoard::tclCtrlBoard( void* poService ) { # if defined Something (void) poService; \\ What does this mean } hyderabadblues wrote: > What does (void) poService in followinf peace of code mean > > tclCtrlBoard::tclCtrlBoard( void* poService ) > { > > # if defined Something > (void) poService; \\ What does this mean > > } > Nothing, it's a waste of typing, remove it. John hyderabadblues wrote: > What does (void) poService in followinf peace of code mean > > t...

reinterpret_cast
Hello, I am trying to convert some C++ code down to kernel-level C code. Some lines have pointers to unsigned chars reinterpreted to unsigned longs. For Example, const unsigned long * datain = reinterpret_cast<const unsigned long*>(datain1); Where datain1 is declared as: const unsigned char * datain1; I don't think a regular cast would suffice. Any suggestions? -Jay (patelj27b at gmail dot com) > const unsigned long * datain = reinterpret_cast<const unsigned > long*>(datain1); Use (ULONG*) cast. "const" is not in favour in the...

void function returning returned void?
Is there a valid reason why a compiler can reject the following? void foo( void ) { /* maybe do things */ return; } void bar( int param ) { if ( param ) return foo(); /* do things */ return; } int main( void ) { int a = 1; bar( a ); return 0; } -- #include <standard.disclaimer> _ Kevin D Quitt USA 91387-4454 96.37% of all statistics are made up -- comp.lang.c.moderated - moderation address: clcm@plethora.net -- you must have an appropriate newsgroups line in your header for your mail to be ...