Topic: Casting from unsigned char* to char*


Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/03
Raw View
Jason Merrill <jason@cygnus.com> writes:

|>  >>>>> James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
|>
|>  > Stephen.Clamage@eng.sun.com (Steve Clamage) writes:
|>
|>  > |>  The description in 5.2.9 "Static Cast" lists the allowed conversions
|>  > |>  and says no others are allowed. "unsigned char*" to "char*" is not
|>  > |>  listed as allowed, and so is invalid.
|>
|>  > But void* to char* IS legal, and of course, unsigned char* converts
|>  > implicitly to void*.
|>
|>  But no implicit conversions are applied to the operand of a cast, so this
|>  is not an issue.

Could you cite where in the draft standard that it says this.  I
couldn't find it.

--
James Kanze      home:     kanze@gabi-soft.fr        +33 (0)1 39 55 85 62
                 office:   kanze@vx.cit.alcatel.fr   +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
     -- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1997/03/03
Raw View
James Kanze wrote:
>
> Stephen.Clamage@eng.sun.com (Steve Clamage) writes:
>
> |>  The description in 5.2.9 "Static Cast" lists the allowed conversions
> |>  and says no others are allowed. "unsigned char*" to "char*" is not
> |>  listed as allowed, and so is invalid.
>
> But void* to char* IS legal, and of course, unsigned char* converts
> implicitly to void*.
>
> I don't think that this was intended, but quite frankly, I don't see a
> simple way of banning it except by banning static_cast from void*.  (I
> guess one could always special case it: the implicit conversion to void*
> cannot be used in the operand of a static_cast.  But I just hate special
> cases.)

This is not my reading of the standard at all. IMO standard
conversions can't be apply in new-style casts unless explicitly
stated; I'd compare this with template argument deduction:

template <class T>
T max (T, T);

max (1, 2.);

doesn't work not because the type are incompatibles, but
because they are differents.

So it's explicitly stated (in both April and Dec DWP) that
static_cast can perform a standard conversion OR the
reverse of most standard conversion.

If std conversions could occur anywhere, then it wouldn'd
be stated that static_cast can perform a std conversion.

So a conforming compiler shouldn't accept
static_cast<int*> (longPtr) even if it has the right to
accept static_cast<int*> (static_cast<void*> (longPtr))
and fail at run-time.

--

Valentin Bonnard
mailto:bonnardv@pratique.fr
http://www.pratique.fr/~bonnardv (Informations sur le C++ en Francais)
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Stephen.Clamage@eng.sun.com (Steve Clamage)
Date: 1997/03/04
Raw View
In article fsf@vx.cit.alcatel.fr, James Kanze
<james-albert.kanze@vx.cit.alcatel.fr> writes:
>
>Jason Merrill <jason@cygnus.com> writes:
>
>|>  >>>>> James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
>|>
>|>  > Stephen.Clamage@eng.sun.com (Steve Clamage) writes:
>|>
>|>  > |>  The description in 5.2.9 "Static Cast" lists the allowed conversions
>|>  > |>  and says no others are allowed. "unsigned char*" to "char*" is not
>|>  > |>  listed as allowed, and so is invalid.
>|>
>|>  > But void* to char* IS legal, and of course, unsigned char* converts
>|>  > implicitly to void*.
>|>
>|>  But no implicit conversions are applied to the operand of a cast, so this
>|>  is not an issue.
>
>Could you cite where in the draft standard that it says this.  I
>couldn't find it.

I believe it is implicit. Each of the X_cast descriptions starts with
a phrase like "The result of the expression X_cast<T>(v) is the result
of converting the expression v to type T." Each section goes on to
describe the constraints on T and v. I don't see any way to read the
descriptions to say that intermediate conversions could take place.

---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/02/26
Raw View
fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson) writes:

|>  "Arnold Woodworth" <arnoldw@westworld.com> writes:
|>
|>  >In article <rf5wws3qv1c.fsf@vx.cit.alcatel.fr>, James Kanze
|>  ><james-albert.kanze@vx.cit.alcatel.fr> wrote:
|>  >
|>  >  > What type of cast should be used to cast an "unsigned char*" to a
|>  >  > "char*"?  I can find nothing in the draft that would suggest that a
|>  >  > static_cast would be legal, and a reinterpret_cast is, of course,
|>  >  > implementation defined, and so not portable.
|>  >
|>  >main()
|>  >{
|>  >    char *string1;
|>  >    unsigned char *string2;
|>  >
|>  >    string1 = (signed char *)string2;
|>  >}
|>
|>  That's not going to help, because `char *' and `signed char *'
|>  are different types (irrespective of whether plain `char' is signed
|>  or not).

As well as the fact that the whole point is "which new-style cast to
use".  I know that the old style cast works, and I know that I can do it
(on all real implementations) using reinterpret_cast.  What I'd like,
however, is something at little bit "safer looking".

(From discussion in another thread, I think that in this case, the
reinterpret_cast is actually well defined by the language standard,
since I don't think that the required alignment of the three char types
can be different.)

--
James Kanze      home:     kanze@gabi-soft.fr        +33 (0)1 39 55 85 62
                 office:   kanze@vx.cit.alcatel.fr   +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
     -- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/02/26
Raw View
Stephen.Clamage@eng.sun.com (Steve Clamage) writes:

|>  In article 1@jake.esu.edu, jpotter@falcon.lhup.edu (John E. Potter) writes:
|>  >James Kanze (james-albert.kanze@vx.cit.alcatel.fr) wrote:
|>  >: What type of cast should be used to cast an "unsigned char*" to a
|>  >: "char*"?  I can find nothing in the draft that would suggest that a
|>  >: static_cast would be legal, and a reinterpret_cast is, of course,
|>  >: implementation defined, and so not portable.
|>  >
|>  >Agreed, but I can not find anything that says it would not be legal
|>  >either.
|>
|>  The description in 5.2.9 "Static Cast" lists the allowed conversions
|>  and says no others are allowed. "unsigned char*" to "char*" is not
|>  listed as allowed, and so is invalid.

But void* to char* IS legal, and of course, unsigned char* converts
implicitly to void*.

I don't think that this was intended, but quite frankly, I don't see a
simple way of banning it except by banning static_cast from void*.  (I
guess one could always special case it: the implicit conversion to void*
cannot be used in the operand of a static_cast.  But I just hate special
cases.)

--
James Kanze      home:     kanze@gabi-soft.fr        +33 (0)1 39 55 85 62
                 office:   kanze@vx.cit.alcatel.fr   +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
     -- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/02/26
Raw View
fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson) writes:

|>  Stephen.Clamage@eng.sun.com (Steve Clamage) writes:
|>
|>  >In article fsf@vx.cit.alcatel.fr, James Kanze
|>  ><james-albert.kanze@vx.cit.alcatel.fr> writes:
|>  >>What type of cast should be used to cast an "unsigned char*" to a
|>  >>"char*"?  I can find nothing in the draft that would suggest that a
|>  >>static_cast would be legal, and a reinterpret_cast is, of course,
|>  >>implementation defined, and so not portable.
|>  >
|>  >You have no choice but reinterpret_cast; none of the others can be used.
|>
|>  That's not quite correct -- an old-style cast still works.

But in this case, the old-style cast IS a reinterpret_cast.  Or have I
misunderstood something?

--
James Kanze      home:     kanze@gabi-soft.fr        +33 (0)1 39 55 85 62
                 office:   kanze@vx.cit.alcatel.fr   +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
     -- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/02/26
Raw View
Stephen.Clamage@eng.sun.com (Steve Clamage) writes:

|>  In article fsf@vx.cit.alcatel.fr, James Kanze
|>  <james-albert.kanze@vx.cit.alcatel.fr> writes:
|>  >What type of cast should be used to cast an "unsigned char*" to a
|>  >"char*"?  I can find nothing in the draft that would suggest that a
|>  >static_cast would be legal, and a reinterpret_cast is, of course,
|>  >implementation defined, and so not portable.
|>
|>  You have no choice but reinterpret_cast; none of the others can be used.
    [...]

Thanks for the answer.

I never doubted that in reality, the reintepret_cast would work.  It
just bothered me that there wasn't a "guaranteed" solution to this
problem.

I'll guess I'll just have to add this to the MaxAlign union: not
formally guaranteed, but any implementation so particular as to make it
not work would probably be useless anyway.

--
James Kanze      home:     kanze@gabi-soft.fr        +33 (0)1 39 55 85 62
                 office:   kanze@vx.cit.alcatel.fr   +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
     -- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/02/26
Raw View
jpotter@falcon.lhup.edu (John E. Potter) writes:

|>  : FWIW: the problem comes up with lex, which generates its tokens in a
|>  : buffer of "unsigned char".  (From recent discussions concerning the
|>  : signedness of char, one can well guess why.)  Of course, the constructor
|>  : for "string" wants a plain char.  Is there any guaranteed portable way
|>  : to convert the token to a string, other than first copying it into an
|>  : array of plain char?
|>
|>  If I read 4.7 [conv.integral] correctly, when char is signed the conversion
|>  from unsigned char to char is implementation defined for those values
|>  which are out of range for char.  That is not portable either.  Of course,
|>  memcpy would copy the bits, but the interpretation of the unsigned char
|>  bits in the char would be implementation defined.

This is not a problem in this particular case.  All of the characters
I'm scanning must be in the C++ basic source character set, and so must
be positive in a plain char.  (If I get a character outside of this set,
the lex'er will complain, since it will not match any regular
expression.)

|>  Would basic_string<unsigned char> solve the problem?

In my case, certainly not, since it isn't furnished with the compiler in
question, and won't compile with it, either:-).

Realistically, I think that using a non-standard (in the sense, not what
other people are using) string will generally cause more problems than
it solves (although it would probably work in my specific case).

|>  : (Presumably, the implementation's definition of
|>  : reinterpret_cast could be to always return a null pointer, which
|>  : strictly speaking eliminates it as a possibility, although the
|>  : probability of such an implementation is, IMHO, quite near 0.)
|>
|>  No, that is not a valid implementation.  5.2.10 [expr.reinterpret.cast]/7
|>  requires that a pointer cast to a type with no stricter allignment and
|>  back must result in the same value.  The mapping is implementation
|>  defined; however, it must be reversable.  Given that requirement,
|>  the obvious mapping is most likely.  Using your tagged pointer example,
|>  I would hope that the implementation would adjust the tags properly
|>  for reinterpret_cast.  For static_cast, it is (un)covered by the
|>  draft.

Yes.  I've since seen this.  In practice, of course, I was never really
worried about the reinterpret_cast failing; portability is limited to
mainstream Unix machines, or perhaps other "popular" platforms (NT,
Mac), but nothing exotic.  My question was purely a standards one: what
can I do that is guaranteed by the standard (as opposed to what is
certain to work in practice).

|>  What does the draft say about the following (effectively from qsort)?
|>
|>  static_cast<int*>(static_cast<void*>(static_cast<char*>(
|>    static_cast<void*>(intArray)) + k * sizeof(int)))

Can you do arithmetic on void*'s?  (Somehow, I didn't think so, but I'm
not really sure.)

--
James Kanze      home:     kanze@gabi-soft.fr        +33 (0)1 39 55 85 62
                 office:   kanze@vx.cit.alcatel.fr   +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
     -- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Jason Merrill <jason@cygnus.com>
Date: 1997/02/27
Raw View
>>>>> James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:

> Stephen.Clamage@eng.sun.com (Steve Clamage) writes:

> |>  The description in 5.2.9 "Static Cast" lists the allowed conversions
> |>  and says no others are allowed. "unsigned char*" to "char*" is not
> |>  listed as allowed, and so is invalid.

> But void* to char* IS legal, and of course, unsigned char* converts
> implicitly to void*.

But no implicit conversions are applied to the operand of a cast, so this
is not an issue.

Jason
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/02/27
Raw View
James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:

 >fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson) writes:
 >
 >|>  Stephen.Clamage@eng.sun.com (Steve Clamage) writes:
 >|>
 >|>  >In article fsf@vx.cit.alcatel.fr, James Kanze
 >|>  ><james-albert.kanze@vx.cit.alcatel.fr> writes:
 >|>  >>What type of cast should be used to cast an "unsigned char*" to a
 >|>  >>"char*"?  I can find nothing in the draft that would suggest that a
 >|>  >>static_cast would be legal, and a reinterpret_cast is, of course,
 >|>  >>implementation defined, and so not portable.
 >|>  >
 >|>  >You have no choice but reinterpret_cast; none of the others can be used.
 >|>
 >|>  That's not quite correct -- an old-style cast still works.
 >
 >But in this case, the old-style cast IS a reinterpret_cast.  Or have I
 >misunderstood something?

In this case, the old-style cast performs the same conversion as a
reinterpret_cast.  In other words, the old-style cast is equivalent in
effect to a reinterpret_cast.  But that doesn't mean that the old-style
cast IS a reinterpret_cast -- after all, the syntax is still quite
different!

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: herbs@cntc.com (Herb Sutter)
Date: 1997/02/22
Raw View
"Arnold Woodworth" <arnoldw@westworld.com> wrote:
>In article <rf5wws3qv1c.fsf@vx.cit.alcatel.fr>, James Kanze
><james-albert.kanze@vx.cit.alcatel.fr> wrote:
>
>  > What type of cast should be used to cast an "unsigned char*" to a
>  > "char*"?  I can find nothing in the draft that would suggest that a
>  > static_cast would be legal, and a reinterpret_cast is, of course,
>  > implementation defined, and so not portable.
>
>main()
>{
>    char *string1;
>    unsigned char *string2;
>
>    string1 = (signed char *)string2;
>}
>
>//  "signed" is a keyword in both C and C++

This code does not solve the problem, since both "unsigned char*" and
"signed char*" are distinct from "char*".

---
Herb Sutter (herbs@cntc.com)

Current Network Technologies Corp.
3100 Ridgeway, Suite 42, Mississauga ON Canada L5L 5M5
Tel 416-805-9088  Fax 905-608-2611
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/02/22
Raw View
Stephen.Clamage@eng.sun.com (Steve Clamage) writes:

>In article fsf@vx.cit.alcatel.fr, James Kanze
><james-albert.kanze@vx.cit.alcatel.fr> writes:
>>What type of cast should be used to cast an "unsigned char*" to a
>>"char*"?  I can find nothing in the draft that would suggest that a
>>static_cast would be legal, and a reinterpret_cast is, of course,
>>implementation defined, and so not portable.
>
>You have no choice but reinterpret_cast; none of the others can be used.

That's not quite correct -- an old-style cast still works.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/02/20
Raw View
What type of cast should be used to cast an "unsigned char*" to a
"char*"?  I can find nothing in the draft that would suggest that a
static_cast would be legal, and a reinterpret_cast is, of course,
implementation defined, and so not portable.

FWIW: the problem comes up with lex, which generates its tokens in a
buffer of "unsigned char".  (From recent discussions concerning the
signedness of char, one can well guess why.)  Of course, the constructor
for "string" wants a plain char.  Is there any guaranteed portable way
to convert the token to a string, other than first copying it into an
array of plain char?  (Presumably, the implementation's definition of
reinterpret_cast could be to always return a null pointer, which
strictly speaking eliminates it as a possibility, although the
probability of such an implementation is, IMHO, quite near 0.)

--
James Kanze      home:     kanze@gabi-soft.fr        +33 (0)1 39 55 85 62
                 office:   kanze@vx.cit.alcatel.fr   +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
     -- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: David R Tribble <david.tribble@central.beasys.com>
Date: 1997/02/21
Raw View
James Kanze <james-albert.kanze@vx.cit.alcatel.fr> wrote:

> What type of cast should be used to cast an "unsigned char*" to a
> "char*"?  I can find nothing in the draft that would suggest that a
> static_cast would be legal, and a reinterpret_cast is, of course,
> implementation defined, and so not portable.

The draft appears to imply by omission that 'static_cast' can't be used
to convert inconvertible pointer types.  However, an old-style cast should
work just fine:

    unsigned char *     ucp;
    char *              cp;

    cp = (char *) ucp;

> FWIW: the problem comes up with lex, which generates its tokens in a
> buffer of "unsigned char".  (From recent discussions concerning the
> signedness of char, one can well guess why.)

It depends on which Lex you're using; some define the token buffer as a
'char[]' while others use 'unsigned char[]'.  This makes Lex, unfortunately,
unportable.  You must use casts and pointers to build a portable layer on
top of Lex.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: herbs@cntc.com (Herb Sutter)
Date: 1997/02/21
Raw View
James Kanze <james-albert.kanze@vx.cit.alcatel.fr> wrote:
>What type of cast should be used to cast an "unsigned char*" to a
>"char*"?  I can find nothing in the draft that would suggest that a
>static_cast would be legal,

Right, unfortunately they're distinct and unrelated types.

>and a reinterpret_cast is, of course,
>implementation defined, and so not portable.

So far I've found nothing better than reinterpret_casts or old-style casts.
It's true that char, signed char, and unsigned char must all have equal
size and the same alignment requirements, but that doesn't guarantee
pointer conversion portability.

>FWIW: the problem comes up with lex, which generates its tokens in a
>buffer of "unsigned char".  (From recent discussions concerning the
>signedness of char, one can well guess why.)  Of course, the constructor
>for "string" wants a plain char.

We encounter this all the time, too.  Our system code that deals with
binary comm streams consistently uses unsigned char*, whereas most of the
standard library and some other libraries use char*.

Note that, in James' case, saying "just use basic_string<unsigned char,
..>" is a nonsolution.  I also would be interested in this answer.

---
Herb Sutter (herbs@cntc.com)

Current Network Technologies Corp.
3100 Ridgeway, Suite 42, Mississauga ON Canada L5L 5M5
Tel 416-805-9088  Fax 905-608-2611
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Stephen.Clamage@eng.sun.com (Steve Clamage)
Date: 1997/02/21
Raw View
In article fsf@vx.cit.alcatel.fr, James Kanze
<james-albert.kanze@vx.cit.alcatel.fr> writes:
>What type of cast should be used to cast an "unsigned char*" to a
>"char*"?  I can find nothing in the draft that would suggest that a
>static_cast would be legal, and a reinterpret_cast is, of course,
>implementation defined, and so not portable.

You have no choice but reinterpret_cast; none of the others can be used.

The signed and unsigned versions of each integer type (including char) are
required to have the same size, representation, and alignment requirements.
That makes it quite likely that a pointer to signed char and pointer to
unsigned char will be interconvertable. In addition, the results of the
reinterpret_cast are "intended to be unsurprising", although that is not
a normative requirement.

If an implementation did not treat those two pointer types alike, you
would certainly have grounds for complaint (just as you would if
the implementation wouldn't let you create a program more than 20
lines long). The exception would be on a system where the two
pointers were incompatible and could not be interconverted for some
odd reason. In that case, you are out of luck anyway (just as you would
be out of luck on an i86 system trying to convert a far pointer to
a near pointer).

I've argued in the past that reinterpret_cast has no portable results.
It might look like I have reversed my position. Not so.

As a practical matter, using reinterpret_cast for this kind of conversion,
or for conversion among pointer types which have similar representation,
is likely to work as you expect. But it is possible that on some system a
reasonable-looking cast just won't work, and the standard doesn't assure
you that it will.
---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "Arnold Woodworth" <arnoldw@westworld.com>
Date: 1997/02/21
Raw View
In article <rf5wws3qv1c.fsf@vx.cit.alcatel.fr>, James Kanze
<james-albert.kanze@vx.cit.alcatel.fr> wrote:

  > What type of cast should be used to cast an "unsigned char*" to a
  > "char*"?  I can find nothing in the draft that would suggest that a
  > static_cast would be legal, and a reinterpret_cast is, of course,
  > implementation defined, and so not portable.

main()
{
    char *string1;
    unsigned char *string2;

    string1 = (signed char *)string2;
}

//  "signed" is a keyword in both C and C++
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: jpotter@falcon.lhup.edu (John E. Potter)
Date: 1997/02/21
Raw View
James Kanze (james-albert.kanze@vx.cit.alcatel.fr) wrote:
: What type of cast should be used to cast an "unsigned char*" to a
: "char*"?  I can find nothing in the draft that would suggest that a
: static_cast would be legal, and a reinterpret_cast is, of course,
: implementation defined, and so not portable.

Agreed, but I can not find anything that says it would not be legal
either.
   static_cast<char*>(static_cast<void*>(unsignedCharPointer))
is legal; so, is
   static_cast<char*>(unsignedCharPointer)
legal because of an implicit conversion to void*?  I find nothing to
say what it would do in either case.

: FWIW: the problem comes up with lex, which generates its tokens in a
: buffer of "unsigned char".  (From recent discussions concerning the
: signedness of char, one can well guess why.)  Of course, the constructor
: for "string" wants a plain char.  Is there any guaranteed portable way
: to convert the token to a string, other than first copying it into an
: array of plain char?

If I read 4.7 [conv.integral] correctly, when char is signed the conversion
from unsigned char to char is implementation defined for those values
which are out of range for char.  That is not portable either.  Of course,
memcpy would copy the bits, but the interpretation of the unsigned char
bits in the char would be implementation defined.

Would basic_string<unsigned char> solve the problem?

: (Presumably, the implementation's definition of
: reinterpret_cast could be to always return a null pointer, which
: strictly speaking eliminates it as a possibility, although the
: probability of such an implementation is, IMHO, quite near 0.)

No, that is not a valid implementation.  5.2.10 [expr.reinterpret.cast]/7
requires that a pointer cast to a type with no stricter allignment and
back must result in the same value.  The mapping is implementation
defined; however, it must be reversable.  Given that requirement,
the obvious mapping is most likely.  Using your tagged pointer example,
I would hope that the implementation would adjust the tags properly
for reinterpret_cast.  For static_cast, it is (un)covered by the
draft.

What does the draft say about the following (effectively from qsort)?

static_cast<int*>(static_cast<void*>(static_cast<char*>(
  static_cast<void*>(intArray)) + k * sizeof(int)))

John
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Stephen.Clamage@eng.sun.com (Steve Clamage)
Date: 1997/02/22
Raw View
In article 002ad8b4@central.beasys.com, David R Tribble
<david.tribble@central.beasys.com> writes:
>James Kanze <james-albert.kanze@vx.cit.alcatel.fr> wrote:
>
>> What type of cast should be used to cast an "unsigned char*" to a
>> "char*"?  I can find nothing in the draft that would suggest that a
>> static_cast would be legal, and a reinterpret_cast is, of course,
>> implementation defined, and so not portable.
>
>The draft appears to imply by omission that 'static_cast' can't be used
>to convert inconvertible pointer types.

Au contraire, the draft is quite explicit. It enumerates the conversions
which are allowed for a static_cast and says "No other conversion shall
be performed explicitly using a static_cast." (5.2.9 Static Cast) The
word "shall" means a violation constitutes an ill-formed program which
must be diagnosed by the C++ implementation.

>  However, an old-style cast should work just fine:
>
>    unsigned char *     ucp;
>    char *              cp;
>
>    cp = (char *) ucp;

The old-style cast notation is defined in terms of the four new-style
casts.  This example old-style cast turns out to be equivalent to
to reinterpret_cast, which returns us to the original question.
---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Stephen.Clamage@eng.sun.com (Steve Clamage)
Date: 1997/02/22
Raw View
In article 1@jake.esu.edu, jpotter@falcon.lhup.edu (John E. Potter) writes:
>James Kanze (james-albert.kanze@vx.cit.alcatel.fr) wrote:
>: What type of cast should be used to cast an "unsigned char*" to a
>: "char*"?  I can find nothing in the draft that would suggest that a
>: static_cast would be legal, and a reinterpret_cast is, of course,
>: implementation defined, and so not portable.
>
>Agreed, but I can not find anything that says it would not be legal
>either.

The description in 5.2.9 "Static Cast" lists the allowed conversions
and says no others are allowed. "unsigned char*" to "char*" is not
listed as allowed, and so is invalid.

>   static_cast<char*>(static_cast<void*>(unsignedCharPointer))
>is legal; so, is
>   static_cast<char*>(unsignedCharPointer)
>legal because of an implicit conversion to void*?  I find nothing to
>say what it would do in either case.

You can use static_cast (or no cast) to convert any data pointer
to void* and not lose any information. You can use static_cast
to convert a void* back to its original type and get a pointer
that compares equal to the original. Your example double cast
has no assigned semantics.

---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/02/22
Raw View
"Arnold Woodworth" <arnoldw@westworld.com> writes:

>In article <rf5wws3qv1c.fsf@vx.cit.alcatel.fr>, James Kanze
><james-albert.kanze@vx.cit.alcatel.fr> wrote:
>
>  > What type of cast should be used to cast an "unsigned char*" to a
>  > "char*"?  I can find nothing in the draft that would suggest that a
>  > static_cast would be legal, and a reinterpret_cast is, of course,
>  > implementation defined, and so not portable.
>
>main()
>{
>    char *string1;
>    unsigned char *string2;
>
>    string1 = (signed char *)string2;
>}

That's not going to help, because `char *' and `signed char *'
are different types (irrespective of whether plain `char' is signed
or not).

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]