Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Converting from int* to char*

95 views
Skip to first unread message

Paul

unread,
Dec 24, 2015, 5:59:55 PM12/24/15
to
I'm confused about when conversions between types are allowed.
int* z = new int(3);
char* x= (char*)z; //works fine.

However, if the second line is replaced by char* x = char*(z); I get "expected primary expression before char" compile error. I was anticipating that I can cast from int* to char* this way in the same way that you can cast 5.3 to int by writing int(5.3);

If the second line is replaced by char*x = z; I get an error -- "can not convert from char* to int* in initialization" How could I have know that such an initialization is illegal, given that the cast of the form char* x = (char*)z; is ok ?

Paul

Paavo Helde

unread,
Dec 24, 2015, 6:34:37 PM12/24/15
to
Paul <peps...@gmail.com> wrote in
news:0be9ea2b-738b-419f...@googlegroups.com:

> I'm confused about when conversions between types are allowed.
> int* z = new int(3);
> char* x= (char*)z; //works fine.
>
> However, if the second line is replaced by char* x = char*(z); I get
> "expected primary expression before char" compile error. I was
> anticipating that I can cast from int* to char* this way in the same
> way that you can cast 5.3 to int by writing int(5.3);

This is a lexical issue, it just does not make sense to multiply a type
char with something. Change it to

char* x = reinterpret_cast<char*>(z);

or

char* x = (char*)(z);

or

typedef char* charPtr;
charPtr x = charPtr(z);

Note that only the first one is really C++.

>
> If the second line is replaced by char*x = z; I get an error -- "can
> not convert from char* to int* in initialization" How could I have
> know that such an initialization is illegal, given that the cast of
> the form char* x = (char*)z; is ok ?

By reading and understanding the language rules?

hth
Paavo

Alf P. Steinbach

unread,
Dec 25, 2015, 7:34:02 AM12/25/15
to
On 12/24/2015 11:59 PM, Paul wrote:
> I'm confused about when conversions between types are allowed.
> int* z = new int(3);
> char* x= (char*)z; //works fine.

Assuming that by "works fine" you mean "no compilation error", then that
doesn't say much, really. Lots of code will compile but will not "work
fine".

However, if you mean that the expression "*x" subsequently yields the
value 3, then that's an artifact of the machine architecture.

Namely, that in this case it stores integers with the least significant
at lowest address, which is called little endian (reportedly due to the
terminology used in Gulliver's Travels, written by Jonathan Swift, whose
poem about the recursiveness of things provided the main inspiration for
Augustus De Morgan's ditto poem about recursive fleas, which, as De
Morgan himself, is frequently mentioned in programming and computer
science books). If instead integers were stored in big endian format, or
worse, in some middle endian jumbled format, you'd get zero.


> However, if the second line is replaced by char* x = char*(z); I get
> "expected primary expression before char" compile error. I was
> anticipating that I can cast from int* to char* this way in the same
> way that you can cast 5.3 to int by writing int(5.3);

Casting pointers generally means you will be interpreting the bitpattern
in some new way.

This is generally known as type PUNNING, and in C++ it can be expressed
as a reinterpret_cast, e.g.

auto x = reinterpret_cast<char*>( z );

In contrast, when you convert 5.3 to int you're generating a new
bitpattern that to some degree, preferably via some precisely defined
formula or algorithm, preserves the original value. This is more
commonly referred to as a CONVERSION. In C++ it can be expressed as a
static_cast, e.g.

auto i = static_cast<int>( 5.3 );

In addition to static_cast and reinterpret_cast there's dynamic_cast,
const_cast and the case of using a C style cast to cast to inaccesible base.

This should ideally be discussed in your textbook?


> If the second line is replaced by char*x = z; I get an error -- "can
> not convert from char* to int* in initialization" How could I have
> know that such an initialization is illegal,

Initializing something of type X with something of type Y is only valid
if there is a single-step implicit conversion from Y to X.

This is a fundamental part of static type checking, which should also be
discussed in your text book?


> given that the cast of
> the form char* x = (char*)z; is ok ?

Oh, the term "OK" can mean so many things here, ranging from "no
compilation error" via "is one of the supported type punnings listed in
the whatever-it-was std's paragraph" to "does what I want".

But what you need to know up front right now is that a C style cast
generally just tells the compiler to "shut up! because I KNOW WHAT I'M
DOING". It also tells the compiler to do whatever is implied by the
current source code. Which can CHANGE when the source is maintained.

Obviously that's not a good idea when one doesn't know what one's doing.

So, preferably just avoid casts.

And when you absolutely need to use a cast, then choose one of the four
named C++ style casts mentioned above, or, if needed, a combination.


Cheers & hth.,

- Alf

R. Schubert

unread,
Jan 8, 2016, 9:07:37 AM1/8/16
to
On Friday, December 25, 2015 at 12:34:37 AM UTC+1, Paavo Helde wrote:
>
> typedef char* charPtr;
> charPtr x = charPtr(z);
>

Why is it even allowed to convert pointers this way without an explicit
reinterpret_cast?

Mr Flibble

unread,
Jan 8, 2016, 12:03:14 PM1/8/16
to
It is: reinterpret_cast is a subset of the C-style cast sausages.

/Flibble


Richard

unread,
Jan 8, 2016, 1:43:38 PM1/8/16
to
[Please do not mail me a copy of your followup]

"R. Schubert" <raphael....@gmx.de> spake the secret code
<5df43103-570f-418b...@googlegroups.com> thusly:
Functional casts (i.e. T(value) to cast value to type T) are just
another way of writing C style casts. A C style cast can be any of:

- static_cast
- const_cast
- reinterpret_cast

I think the compiler is even free to do dynamic_cast.

This is why C style casts are bad form in a C++ code base. From
reading the code, you not only don't know what you're getting from the
compiler without thinking really hard about it, you have no idea what
the original programmer *intended* when they wrote the C style cast.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Alf P. Steinbach

unread,
Jan 9, 2016, 1:34:29 AM1/9/16
to
On 1/8/2016 7:43 PM, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> "R. Schubert" <raphael....@gmx.de> spake the secret code
> <5df43103-570f-418b...@googlegroups.com> thusly:
>
>> On Friday, December 25, 2015 at 12:34:37 AM UTC+1, Paavo Helde wrote:
>>>
>>> typedef char* charPtr;
>>> charPtr x = charPtr(z);
>>>
>>
>> Why is it even allowed to convert pointers this way without an explicit
>> reinterpret_cast?
>
> Functional casts (i.e. T(value) to cast value to type T) are just
> another way of writing C style casts. A C style cast can be any of:
>
> - static_cast
> - const_cast
> - reinterpret_cast

OK.

> I think the compiler is even free to do dynamic_cast.

No, but it can cast to inaccessible base, as a `static_cast` would have
done (including possible address adjustment) if it had been accessible.


> This is why C style casts are bad form in a C++ code base. From
> reading the code, you not only don't know what you're getting from the
> compiler without thinking really hard about it, you have no idea what
> the original programmer *intended* when they wrote the C style cast.

R. Schubert

unread,
Jan 11, 2016, 8:18:26 AM1/11/16
to
On Friday, January 8, 2016 at 7:43:38 PM UTC+1, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> "R. Schubert" <> spake the secret code
> <> thusly:
>
> >On Friday, December 25, 2015 at 12:34:37 AM UTC+1, Paavo Helde wrote:
> >>
> >> typedef char* charPtr;
> >> charPtr x = charPtr(z);
> >>
> >
> >Why is it even allowed to convert pointers this way without an explicit
> >reinterpret_cast?
>
> Functional casts (i.e. T(value) to cast value to type T) are just
> another way of writing C style casts. A C style cast can be any of:
>
> - static_cast
> - const_cast
> - reinterpret_cast
>
> I think the compiler is even free to do dynamic_cast.
>
> This is why C style casts are bad form in a C++ code base. From
> reading the code, you not only don't know what you're getting from the
> compiler without thinking really hard about it, you have no idea what
> the original programmer *intended* when they wrote the C style cast.
> --
> "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
> The Computer Graphics Museum <http://computergraphicsmuseum.org>
> The Terminals Wiki <http://terminals.classiccmp.org>
> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

I see. I thought that only (T)value denoted the C-style cast,
while T(value) would always create a temporary directly initialized
from value and thus require value to be convertible to T, but
apparently I was mistaken. §5.2.3 (Explicit type conversion) of
N3797 even says so, I just didn't find it before. Thanks.


Richard

unread,
Jan 12, 2016, 3:04:43 PM1/12/16
to
[Please do not mail me a copy of your followup]

"R. Schubert" <raphael....@gmx.de> spake the secret code
<d0d395cc-f342-423e...@googlegroups.com> thusly:

>I see. I thought that only (T)value denoted the C-style cast,
>while T(value) would always create a temporary directly initialized
>from value and thus require value to be convertible to T, but
>apparently I was mistaken. §5.2.3 (Explicit type conversion) of
>N3797 even says so, I just didn't find it before. Thanks.

Yeah, I used to think the same thing and then I dug into the standard
and was surprised to find out it explicitly says that this is just
another form of C-style cast.

Now, if you had written T{value}, *that* would be an explicit
construction of a value of type T initialized to value and would
prohibit narrowing conversions.

In a C++11 code base, I think I would prefer something like:

char c = char{14};

over

char c = static_cast<char>(14);

Öö Tiib

unread,
Jan 12, 2016, 3:54:54 PM1/12/16
to
On Tuesday, 12 January 2016 22:04:43 UTC+2, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> "R. Schubert" <raphael....@gmx.de> spake the secret code
> <d0d395cc-f342-423e...@googlegroups.com> thusly:
>
> >I see. I thought that only (T)value denoted the C-style cast,
> >while T(value) would always create a temporary directly initialized
> >from value and thus require value to be convertible to T, but
> >apparently I was mistaken. §5.2.3 (Explicit type conversion) of
> >N3797 even says so, I just didn't find it before. Thanks.
>
> Yeah, I used to think the same thing and then I dug into the standard
> and was surprised to find out it explicitly says that this is just
> another form of C-style cast.
>
> Now, if you had written T{value}, *that* would be an explicit
> construction of a value of type T initialized to value and would
> prohibit narrowing conversions.
>
> In a C++11 code base, I think I would prefer something like:
>
> char c = char{14};
>
> over
>
> char c = static_cast<char>(14);

The characters 14 and 15 were used to change between color ribbons
of prehistoric printers. Did any of those really survive until 2011?
0 new messages