473,842 Members | 1,594 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Safely casting pointer types, purpose of static_cast, etc.

There have been some recent threads about casting pointers to and from
void* that have me rethinking some of my usual practices. I have a
couple of questions.

1. What is the purpose of C++'s static_cast<>? In other words, is
there any real difference between statements like (with non-pointer
types):

double a = 3.4;
int b = (int)a; // <--- this
int c = static_cast<int >(a); // <---

2. What about static cast with void*'s and pointers to class types, is
there any difference here, and also, are these conversions all safe:

Object *a = new Object;
void *b = a;
Object *c = (Object *)b;
Object *d = static_cast<Obj ect *>(b);

In that code is there any difference between the conversion when
initializing c and d? And, are c/d guaranteed to be valid pointers to
the same object a points to?

3. If c/d are not guaranteed to be valid pointers, what is the correct
way to do that conversion in a situation where a void* must be used as
an intermediate variable to hold a pointer to an object (e.g. when
passing through a layer of C code)? For example, when creating a
thread with pthread_create, a void* parameter can be passed to the
thread function. So, then, is the following code guaranteed to always
do what I want on any platform:

=== BEGIN EXAMPLE ===

class A {
public:
void CreateThread ();
private:
void * MyThreadProc_ ();
static void * SThreadProc_ (void *);
};

// creates a thread
void A::CreateThread () {
pthread_t tid;
// 4th param is void* param to pass to SThreadProc_.
pthread_create( &tid, NULL, &SThreadProc _, this);
}

// static thread function calls ((A*)va)->MyThreadProc_( );
void * A::SThreadProc_ (void *va) {
A *a = (A *)va; // <--- is this always safe?
return a->MyThreadProc_( );
}

=== END EXAMPLE ===

Thanks,

Jason
Jun 27 '08 #1
5 3920
There is not much difference but static casting is more
restrictive(saf er) and noticeable.

On Jun 4, 4:21 pm, "jason.cipri... @gmail.com"
<jason.cipri... @gmail.comwrote :
There have been some recent threads about casting pointers to and from
void* that have me rethinking some of my usual practices. I have a
couple of questions.

1. What is the purpose of C++'s static_cast<>? In other words, is
there any real difference between statements like (with non-pointer
types):

double a = 3.4;
int b = (int)a; // <--- this
int c = static_cast<int >(a); // <---

2. What about static cast with void*'s and pointers to class types, is
there any difference here, and also, are these conversions all safe:

Object *a = new Object;
void *b = a;
Object *c = (Object *)b;
Object *d = static_cast<Obj ect *>(b);

In that code is there any difference between the conversion when
initializing c and d? And, are c/d guaranteed to be valid pointers to
the same object a points to?

3. If c/d are not guaranteed to be valid pointers, what is the correct
way to do that conversion in a situation where a void* must be used as
an intermediate variable to hold a pointer to an object (e.g. when
passing through a layer of C code)? For example, when creating a
thread with pthread_create, a void* parameter can be passed to the
thread function. So, then, is the following code guaranteed to always
do what I want on any platform:

=== BEGIN EXAMPLE ===

class A {
public:
void CreateThread ();
private:
void * MyThreadProc_ ();
static void * SThreadProc_ (void *);

};

// creates a thread
void A::CreateThread () {
pthread_t tid;
// 4th param is void* param to pass to SThreadProc_.
pthread_create( &tid, NULL, &SThreadProc _, this);

}

// static thread function calls ((A*)va)->MyThreadProc_( );
void * A::SThreadProc_ (void *va) {
A *a = (A *)va; // <--- is this always safe?
return a->MyThreadProc_( );

}

=== END EXAMPLE ===

Thanks,

Jason
Jun 27 '08 #2
In article <d5ce22d0-225b-42e4-8d6c-
c4**********@l4 2g2000hsc.googl egroups.com>, ja************@ gmail.com
says...

[ ... ]
1. What is the purpose of C++'s static_cast<>? In other words, is
there any real difference between statements like (with non-pointer
types):

double a = 3.4;
int b = (int)a; // <--- this
int c = static_cast<int >(a); // <---
There is no difference between these statements. For that matter,

int c = 3.4;

is allowed, and does exactly the same thing as well.

The reason for static_cast over a C-style cast is mostly that it is more
restricted, and does NOT support some more dangerous conversions that C-
style casts can do. For example, a C-style cast can do roughly the same
thing as a const_cast, casting away const-ness, or it can do roughly the
same thing as a reinterpret_cas t, treating a pointer as if it pointed to
a different type of operand.
2. What about static cast with void*'s and pointers to class types, is
there any difference here, and also, are these conversions all safe:

Object *a = new Object;
void *b = a;
Object *c = (Object *)b;
Object *d = static_cast<Obj ect *>(b);

In that code is there any difference between the conversion when
initializing c and d? And, are c/d guaranteed to be valid pointers to
the same object a points to?
Yes, the conversions to c and d are the same. A C-style cast does the
same thing as a static_cast when/if a static_cast can do the conversion.
A static_cast can't do anything new that a C-style cast can't. The
advantage of a static_cast is solely that it is more restricted, so you
can't, for one example, accidentally cast away const-ness and/or
reinterpret what a pointer points at -- for example:

int const *a;
char *b = (char *)a; // perfectly legal
char *b = static_cast<cha r *>(a); // not allowed

The C-style cast is casting away the const-ness AND reintrepting what's
pointed at as a char instead of an int. A static_cast simply can't do
that -- if you really want to cast away const-ness, you need to use
const_cast. If you want to reinterpret what's pointed at, you have to
use reinterpret_cas t. If you want to do both, you have to use both:

char *c = const_cast<char *>(reinterpret_ cast<char const *>(a));

The C-style cast can do so many different kinds of conversions, with
nothing to distinguish between them, that it's easy to accidentally do a
conversion you don't want along with the one(s) you did. The new-style
casts attempt to prevent that.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jun 27 '08 #3
On Jun 5, 1:21 am, "jason.cipri... @gmail.com"
<jason.cipri... @gmail.comwrote :
There have been some recent threads about casting pointers to
and from void* that have me rethinking some of my usual
practices. I have a couple of questions.
1. What is the purpose of C++'s static_cast<>?
To limit the types of casts which can be done. You can't
accidentally cast away const with it, for example. More
importantly, in a class hierarchy, a C style cast is a
static_cast if it is to a base or a derived, but a
reinterpret_cas t (i.e. type punning) if it is to a sibling. (An
attempt to use static_cast in this case will cause compiler
error.) Also, static_cast (and dynamic_cast) respect the access
specifiers in an inheritance hierarchy; C style casts don't.
In other words, is there any real difference between
statements like (with non-pointer types):
Unless the types are pointers or references in an inheritance
hierarchy, there is not difference between a C style cast and a
static_cast, *if* the static_cast is legal. For non-pointer and
non-reference types, in fact, most code I've seen doesn't use
static_cast, but rather the function style casts, e.g.:
"MyClass( 43 )".
double a = 3.4;
int b = (int)a; // <--- this
int c = static_cast<int >(a); // <---
These two are totally indentical. Conceptually, I tend to think
of this as creating a new temporary object, rather than
accessing an existing object through a different type. In such
cases, I'll use a function style cast, or a C style cast with
the argument in parentheses, i.e. "int( a )" or "(int)( a )".
(The latter is necessary if the typename is not a single token,
e.g. "unsigned char".) In my mind, this is the syntax for
"creating a new, temporary object".

(Technically, a pointer cast also creates a new, temporary
object. But the new object is a pointer, and of course, for the
most part, when you use a pointer cast, you're concerned about
the access through the pointer.)
2. What about static cast with void*'s and pointers to class
types, is there any difference here, and also, are these
conversions all safe:
Object *a = new Object;
void *b = a;
Object *c = (Object *)b;
Object *d = static_cast<Obj ect *>(b);
In that code is there any difference between the conversion
when initializing c and d? And, are c/d guaranteed to be valid
pointers to the same object a points to?
No difference, and yes. You can convert any pointer type to
void*, and convert it back *to* *the* *same* *type* without loss
of information. (Note that this more or less implies that void
pointers will be at least as large as any other pointer type.)
3. If c/d are not guaranteed to be valid pointers,
Irrelevant, because they are. I'd use static_cast in this case.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #4
On Jun 5, 1:21 am, "jason.cipri... @gmail.com"
<jason.cipri... @gmail.comwrote :

[...]
3. If c/d are not guaranteed to be valid pointers,
As I said, they are guaranteed to be valid, but I missed some
important issues in your example.
what is the correct way to do that conversion in a situation
where a void* must be used as an intermediate variable to hold
a pointer to an object (e.g. when passing through a layer of C
code)? For example, when creating a thread with
pthread_create, a void* parameter can be passed to the thread
function. So, then, is the following code guaranteed to always
do what I want on any platform:
=== BEGIN EXAMPLE ===
class A {
public:
void CreateThread ();
private:
void * MyThreadProc_ ();
static void * SThreadProc_ (void *);
};
// creates a thread
void A::CreateThread () {
pthread_t tid;
// 4th param is void* param to pass to SThreadProc_.
pthread_create( &tid, NULL, &SThreadProc _, this);
}
// static thread function calls ((A*)va)->MyThreadProc_( );
void * A::SThreadProc_ (void *va) {
A *a = (A *)va; // <--- is this always safe?
return a->MyThreadProc_( );
}
=== END EXAMPLE ===
First, this won't compile with a compliant compiler. The type
of the third parameter to pthread_create is ``extern "C" void*
(*) (void*)'', and a member function, even static, can never
have a type with ``extern "C"''. You *must* use a free function
for this.

Secondly, as I said in my previous answer, the type you get from
the void* *must* be the same type as you used to create it.
That's not a problem here, but it very much could be if you
derive. A common mistaken idiom is something like:

class ThreadBase
{
public:
virtual ~ThreadBase() {}
virtual void run() = 0 ;
} ;

extern "C" void*
threadStarter( void* p )
{
static_cast< ThreadBase* >( p )->run() ;
return NULL ;
}

class MyThread : public ThreadBase
{
public:
virtual void run() ;
// ...
} ;

and then somewhere:

MyThread t ;
pthread_t ti ;
pthread_create( &ti, NULL, &threadStart er, &t ) ;

This does *not* work. Or rather, it is undefined behavior,
which may seem to work in some frequent cases. The last line
must be:

pthread_create( &ti, NULL, &threadStart er,
static_cast< ThreadBase* >( &t ) ) ;

for the behavior to be guaranteed---the cast from void* is to
ThreadBase*, so the void* must have been created from a
ThreadBase*, and not a MyThread*.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #5
Sorry, there's too much to quote, but thanks Jayesh, Jerry, James, for
the complete answers, and for keeping the non-J riff raff out as well.

- Jason
Jun 27 '08 #6

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

Similar topics

4
3487
by: Jacob Jensen | last post by:
This question has probably been asked a million time, but here it comes again. I want to learn the difference between the three type cast operators: static_cast, reinterpret_cast, dynamic_cast. A good way to do this is by example. So I will give an example and please tell me what you think: I have a base class A with a virtual destructor, and a class B that is it inherits publicly from A and defines som extra stuff.
16
2446
by: He Shiming | last post by:
Hi, I'm having a little bit of trouble regarding pointer casting in my program. I don't understand why the following two cases produce different results. Case 1: IInterface *pInterface = new CImplementation(); pInterface->Method(); Case 2:
44
2246
by: Agoston Bejo | last post by:
What happens exactly when I do the following: struct A { int i; string j; A() {} }; void f(A& a) { cout << a.i << endl;
33
3670
by: Mark P | last post by:
A colleague asked me something along the lines of the following today. For some type X he has: X* px = new X; Then he wants to convert px to a char* (I'm guessing for the purpose of serializing the object array). I can think of three ways to do this:
5
5933
by: brekehan | last post by:
I've always been a little sketchy on the differences between static, dynamic, and reinterpret casting. I am looking to clean up the following block by using C++ casting instead of the C style casting. from what I am reading, I should use reinterpret cast in this situation, is that correct? Why does static and dynamic casting fail me? // please excuse the windows types, it is necessary in this code, // but the question remains C++ related
9
2464
by: Jess | last post by:
Hello, It seems both static_cast and dynamic_cast can cast a base class pointer/reference to a derived class pointer/reference. If so, is there any difference between them? In addition, if I have a derived class object and then upcast it to its base class, which cast operator should I use? Is it static_cast, or, can I simply cast it implicitly without any operator? Does this upcasting remove the derived class portion of the object?...
7
2915
by: Christopher Pisz | last post by:
My problem is my derived class is getting called twice instead of the base and then the derived. I thought this was the purpose for virtuals and dynamic casting :/ I want my base class to have its method called and then the derived class have its method called. What am I not understanding? Int the following code, my Event Tester class is getting called twice for keyboard events when I step through the debugger:...
9
3470
by: Taras_96 | last post by:
Hi everyone, I was experimenting with static_cast and reinterpret cast #include <iostream> struct A1 { int a; }; struct A2 { double d; }; struct B : public A1, A2
4
3047
by: Wally Barnes | last post by:
Can someone help a poor C++ programmer that learned the language before there was a standard lib .. etc ? Basically I have two classes that look something like below: template <class T> class ListLogic { public: struct LogicBase {
0
9715
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10945
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10612
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10672
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9453
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7858
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7038
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5696
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
3
3145
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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

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