Casting pointers in C++? - c++

Running this code returns what I assume to be the integer value of realPtr's address.
I'm still new to C++ and I was wondering - is it possible to convert from one data type pointer to another and the pointer variable whose value is assigned will still print out the right value (i.e. *integerPtr prints out 2)?
Code snippet
double real = 2.0;
double *realPtr = ℜ
int *integerPtr;
integerPtr = ((int*)&realPtr);
cout << *integerPtr << endl;
Output
1606416424
Thanks!

There are 3 totally different types that you are dealing with here:
Pointers point to any location in memory. Every pointers are basically the same type, but they are treated as different types depending on what you declare them to point to.
int, and double are types that represent integer and real numeric value; An integer and a double representing the same numerical value (e.g. 2) will not have the same binary content as stipulated by the relevant standard defining how integers and floating point numerics are stored in memory.
Since every pointers are essentially the same type, you may cast a kind of pointer to any other kind. Let's say you have your own Foo class that has nothing to do with representing numerical value. You may still do this:
int* p_int = 2;
Foo* p_foo = (Foo*) p_int;
This is legal, but this will most probably lead to an error, unless the memory representation of a Foo object is akin to that of an int.
If you want to cast an int to a double, you must cast the data, casting the pointer won't do anything. That's why there are several cast with different names in C++11, and it is considered good practice to use them since by doing so you express explicitly what you want to be done. In your case, you may want one of two different things
Reinterpret_cast
Casting a pointer to an int to a pointer to a double, which means essentially doing nothing except telling the compiler that it can safely assume that the data pointed to can be considered as a double. The compiler will assume so, and it is your responsibility to assure that it is the case. This type of cast is considered the most dangerous since as we all know, programmers can't be trusted. It is called a reinterpret_cast:
int* p_int = 2;
Foo* p_foo = reinterpret_cast<int>(p_int);
Same code as above, but we express the danger in the scary "reinterpret_cast". p_int and p_foo have the same value, we did nothing except expressing the fact that we now consider the address of our integer as an address to a foo.
Static_cast
If you want a real cast, you have to operate on the data, not on the pointer. Casting a type of data to another by whatever means the compilers know of is called static_cast. This is probably what you want to do here:
int i = 2;
p_int = &i;
double d = static_cast<double>(i);
p_double = &d; //p_int and p_double have different values since they point to different objects.
The compiler will look for a conversion function from int to double, and yell at you if it doesn't find any.
Of course, there is nothing wrong with doing the exact same thing by using only pointers, although it makes the code slightly less readable (you should be wary of using pointers at all, and do it for a good reason):
int* p_i = 2;
int* p_d = static_cast<double>(*p_i) // p_d is a pointer to a double initialized to the value obtained after converting the int pointed to by p_i

The internal representation of float/dobule and integer data types are different. In a 32 bit PC Integer will take 4 bytes while a double take 8 bytes.
Also there is a serious bug in your code.
double real = 2.0;
double *realPtr = ℜ
int *integerPtr;
integerPtr = ((int*)&realPtr);
cout << *integerPtr << endl;
In the above code see the bold lines. There you declared a pointer to an integer called "integerPtr". But the actual value stored address of a pointer to a double. ie &realPtr is double ** (Pointer to a pointer which holds a double type value). And then you are trying to print the value using *integerPtr.
So I changed your code as follows and it gives a value of 0.
double real = 2.0;
double *realPtr = ℜ
int *integerPtr;
integerPtr = ((int*)realPtr);
std::cout << *integerPtr << std::endl;

Related

C++ single * and **

I am trying to understand why these two lines produce the same result (test and test2).
customClass* test= (customClass*)*(uintptr_t*)(someAddr);
customClass* test2 = *(customClass**)(someAddr);
From what I gathered it's either double dereference or pointer to pointer (in this case).
someAddr refers to pointer to pointer to customClass class in memory
I am trying to understand why these two lines produce the same result (test and test2).
Because undefined behaviour means anything is allowed, even things that don't make sense1.
The value in someAddr is a pointer value, but that doesn't mean you can interpret it as whatever pointer type you like. What it points to is either a someClass *, or a uintptr_t, or something else, it can't be both at the same time.
Therefore one of those lines is breaking the strict aliasing rule, and thus has undefined behaviour. I would presume that it really is a someClass ** value, so use an appropriate cast for that, i.e. std::reinterpret_cast<someClass **>(someAddr)
In this case, treating the value pointed to by someAddr as a pointer-sized number, then reinterpreting that as a someClass * matches how a someClass ** is implemented. It would be ok to have
uintptr_t otherAddr;
memcpy(&otherAddr, reinterpret_cast<void*>(someAddr), sizeof(uintptr_t));
customClass* test3 = reinterpret_cast<customClass*>(otherAddr);
If you can't read complex statements, break them up into lots of simple statements.
(uintptr_t*)(someAddr) casts someAddr (which I assume is some form of pointer) to a pointer-to-uintptr_t.
So, replace this with the statement
uintptr_t* A = (uintptr_t*)(someAddr);
note that uintptr_t is defined as an unsigned integer type large enough to hold a pointer
*(uintptr_t*)(someAddr) is now just *A which is a reference to uintptr_t
So, replace this with
uintptr_t& B = *A;
(customClass*)*(uintptr_t*)(someAddr) is now just (customClass*)B, which means we're converting the integer-large-enough-to-hold-a-pointer back into a pointer.
See the second and third notes on reinterpret_cast, and replace this code with
customClass* test = reinterpret_cast<customClass*>(B);
So the first line ends up as
uintptr_t* A = (uintptr_t*)(someAddr);
uintptr_t& B = *A;
customClass* test = reinterpret_cast<customClass*>(B);
Notice that since uintptr_t is being used to hold a pointer, we're really treating the original address as a pointer-to-pointer. That's how we de-reference one pointer and still end up with a pointer.
Now look again at
customClass* test2 = *(customClass**)(someAddr);
and see it's doing roughly the same thing.
The problem is that although uintptr_t and customClass* are losslessly-convertible, that doesn't mean it's OK to either alias them or to assume they're layout-compatible. You still need to know what type of object you currently have, in order to correctly convert it to the other.
Which type you currently have depends on what was stored there originally, so only one of the statements can be correct.

In C++, why is mentioning the type of the pointer necessary?

In C++, mentioning the type of pointer is necessary. For example,
int a = 5;
int * p = &a;
Here, 'int' in the 'int *' was necessary. The reasons I found are
that its needed for dereferencing.(Knowing no. of bytes to read, and their interpretation) and Pointer Arithmetic.
However, if I write:-
int a = 5;
char * p = &a;
float * p2 = &a;
//etc
Error is shown, saying that a char*,float* etc. pointer can't be assigned to an int variable. Ok.., so the compiler Knew the type of variable for whom I wanted a pointer for. This is unlike normal variables, where compiler doesn't know exactly which type I want. For example:-
int a = 5;
float b = 5;
double c = 5;
long d = 5;
char e = 5;
All these are perfectly fine. I need to write the type here as compiler won't know which type I want, as all of these would work.
However, in case of pointers, it knows the exact type of variable for which I want to declare a pointer to.
Even if I use explicit typecasting, still, I will be in a way telling the type of pointer I need, and still will have to specify the correct pointer type as well.
int a = 5;
char * b = (char*)&a;//This would work.
//However this,
int * b = (char*)&a;
//wouldn't, as even with typecasting, c++ knows exactly the type of pointer we need.
So, my question is, why doesn't C++ automatically set the type of pointer, when it knows the type of variable I am going to point to? When it can give error on not using the correct type of pointer, why not set it automatically?
If you declare b as auto, the compiler will use type inference and determine the type itself. But if you use a specific type, it has to be the correct one.
One possible reason is byte level manipulation of data.
For example, you can have a void* pointer (pointing tosome inner byte data) that can be acessed by *int or *char or whatever pointer you need depending on how you want to read or write data on it.
Mentioning the type indicates how your memory will store the data, in particular the number of memory cases, each type of data has its own size for example (see sizeof ()), working with low level languages sollicits attention on memory and hardware.
For example, the memory representation of a double is not the same as int, or any other type of data, even if they will print the same value as output (in case of implicite conversion), but in the stack, they are not completely the same "value". So the compiler will not allow this in case of pointers.
Using the keyword auto can manage what you are looking for.

Can a pointer point to a value and the pointer value point to the address?

Normal pointer usage as I have been reading in a book is the following:
int *pointer;
int number = 5;
pointer = &number;
Then *pointer has a value of 5.
But does this work the other way around? I mean:
int *pointer;
int number = 5;
*pointer = &number;
Here does pointer contain the value 5 and *pointer holds the address of number?
Thanks.
In
int *pointer;
int number = 5;
*pointer = &number;
you never assign a valid address to pointer, so dereferencing that pointer (as is done by the expression *pointer) is not valid.
Analogy from the department of far-fetched analogies:
You use pointers many times every day without even thinking about it.
A pointer is an indirection - it tells you where something is, or how it can be reached, but not what that thing is.
(In a typed language, you can know what kind of thing it is, but that's another matter.)
Consider, for example, telephone numbers.
These tell you how to reach the person that the phone number belongs to.
Over time, that person may change - perhaps somebody didn't pay their bills and the number was reassigned - but as long as the number is valid, you can use it to reach a person.
Using this analogy, we can define the following operations:
&person gives you a person's phone number, and
*number gives you the person that the number belongs to.
Some rules:
There are only two types in this language - persons and phone numbers.
Only persons can have phone numbers; &number is an error, as is *person.
An unspecified phone number reaches the General Manager of Customer Services at Acme, Inc.
Now, your first example would translate to
PhoneNumber n;
Person Bob;
n = &Bob;
which makes sense; n now holds Bob's phone number.
Your second example would translate to
PhoneNumber n;
Person Bob;
*n = &Bob;
which would say "replace the General Manager of Acme Inc's Customer Services with Bob's phone number", which makes no sense at all.
And your final question,
Here does pointer contain the value 5 and *pointer holds the address of number?
would translate to
Is this phone number the same thing as Bob, and if you call it, will Bob's phone number answer?
which I am sure you can see is a rather strange question.
Your second case will not compile, because the assignment *pointer = &number involves incompatible types (int on the left, a pointer to int on the right) which makes the assignment invalid.
If you somehow coerce the assignment into compiling, then pointer is not initialised. Accessing its value, let alone dereferencing it (e.g. evaluating *pointer or assigning to it as in *pointer = number or *pointer = 5) gives undefined behaviour. Anything can happen then .... depending on circumstances, a common result of undefined behaviour is an abnormal program termination.
*pointer = &number; is not valid C.
*pointer is of type int and &number is of type int*. This isn't a valid form of assignment and will not compile on a standard C compiler.
You can store numbers inside pointer variables, but then you must use an explicit cast to force a type conversion. Some compilers allow it without an explicit cast, but note that doing so is a non-standard extension.
And of course, note that you haven't set pointer to point at an allocated memory address, so you can't store anything inside where it points.
If you do an explicit cast such as
pointer = &something;
*pointer = (int)&number;
then it is allowed in C, but if you try to de-reference that pointer, the behavior is implementation-defined. It could possibly also be undefined behavior in case of misalignment etc. See C11 6.3.2.3:
An integer may be converted to any pointer type. Except as previously
specified, the result is implementation-defined, might not be
correctly aligned, might not point to an entity of the referenced
type, and might be a trap representation.
When you create a pointer variable, initially it will have garbage value (let say 300 address location). Hence when you dereference pointer(*300), it would give another garbage value(value at 300 address location) or error (strictly speaking anything may happen depending on your computer).
In the third step, &number:- which is also another number and your are trying to assign a number to *pointer(may be another number) which not possible. (It is like this:- 5=6). Hence it will be an error.
For you to write an assignment x = y, both x and y must be, or be implicitly convertible to, the same type (or x must have a user-defined assignment operator taking an argument matching the type of y, or ... OK, there are a few possibilities, but you get the idea).
Now, let's look at the statement
*pointer = &number;
Here, *pointer has type int& - you followed the pointer to get a (reference to) the integer stored at that location. Let's ignore, for now, the fact that your pointer was uninitialized and following it results in undefined behaviour.
The right hand side, &number, is taking a pointer to an integer variable, so the type is int*.
So, the expression doesn't make sense at all, just in terms of the type system: there is no way to assign int* to int&. It doesn't mean anything.
Let's relate it back to the English language of your question
Here does pointer contain the value 5 and *pointer holds the address of number?
That translates directly to the type system, and hence also doesn't mean anything. Again, we can break it down
does pointer contain the value 5
a pointer contains a location. The only time it would make sense to talk about a pointer having a literal value (other than nullptr) would be on a platform where there were well-known addresses - this is rare, and '5' is very unlikely to be a well-formed address anyway
*pointer holds the address
well, there is a case where *pointer could hold an address - it's where *pointer is itself is a pointer, meaning the variable pointer is a pointer-to-pointer such as int **. That isn't the case here: we know the type of *pointer in your code, and it is int&, not int*.

Type Casting in C++

I am reading a C++ book and have a problem with the static casting. Here is a function:
void fun(int*pi)
{
void *pv = pi
int *pi2 = static_cast<int*>(pv); //explicit conversion back to int*
double *pd3 = static_cast<double*>(pv); //unsafe
}
The last statement:
double*pd3 = static_cast<double*>(pv);
is considered as unsafe. I don't get why it is considered unsafe.
The cast reinterprets the bits of the pointed to int, plus possibly bits of some following memory (if there is!), as a double value.
A double is (1) typically larger than an int, and (2) has some internal structure.
Point (1) means that any use of the dereferenced result pointer, may access memory that just isn't accessible, beyond the int.
Point (2) means that the arbitrary bitpattern, may be invalid as a double bitpattern, and may cause a hardware exception a.k.a. a "trap" when it's used. From a C++ point of view that's Undefined Behavior. From a practical programming point of view it's typically a "crash".
In contrast, accessing the bits of a double as an int is usually in-practice safe, even though it's formally UB, because (1) an int is typically smaller or equal in size to double, and (2) an int usually does not have any invalid bit patterns. However, depending on the compiler options the compiler may not be happy about doing that directly.
Above I forgot to mention alignment, as Loki Astari pointed out in a comment. And that's a reason (3) for unsafety. As an example, with some given implementation an int may be allowed to have an address that is a multiple of 4, while a double may be required to reside at an address that is a multiple of 8. Then the dereferenced pointer may access a double at an address such that isn't a multiple of 8, causing a trap (more formally, UB where anything can happen).
Because the size of a double pointer is not the same as an int pointer, and if you try to use it, you might get a segmentation fault. They are not necessarily compatible types.
You can try casting the value pointed by pi2.
void fun(int*pi)
{
void *pv = pi;
int *pi2 = static_cast<int*>(pv);
double d = static_cast<double>(*pi2);
std::cout << d; // 42
}
int main()
{
int i = 42;
fun(&i);
}

Casting between integers and pointers in C++

#include<iostream>
using namespace std;
int main()
{
int *p,*c;
p=(int*)10;
c=(int*)20;
cout<<(int)p<<(int)c;
}
Somebody asked me "What is wrong with the above code?" and I couldn't figure it out. Someone please help me.
The fact that int and pointer data types are not required to have the same number of bits, according to the C++ standard, is one thing - that means you could lose precision.
In addition, casting an int to an int pointer then back again is silly. Why not just leave it as an int?
I actually did try to compile this under gcc and it worked fine but that's probably more by accident than good design.
Some wanted a quote from the C++ standard (I'd have put this in the comments of that answer if the format of comments wasn't so restricted), here are two from the 1999 one:
5.2.10/3
The mapping performed by reinterpret_cast is implementation defined.
5.2.10/5
A value of integral type or enumeration type can be explicitly converted to a pointer.
A pointer converted to an integer of sufficient size (if ant such exists on the implementation)
and back to the same pointer type will have its original value; mappings between pointers and
integers are otherwise implementation-defined.
And I see nothing mandating that such implementation-defined mapping must give a valid representation for all input. Otherwise said, an implementation on an architecture with address registers can very well trap when executing
p = (int*)10;
if the mapping does not give a representation valid at that time (yes, what is a valid representation for a pointer may depend of time. For instance delete may make invalid the representation of the deleted pointer).
Assuming I'm right about what this is supposed to be, it should look like this:
int main()
{
int *p, *c;
// Something that creates whatever p and c point to goes here, a trivial example would be.
int pValue, cValue;
p = &pValue;
c = &cValue;
// The & operator retrieves the memory address of pValue and cValue.
*p = 10;
*c = 20;
cout << *p << *c;
}
In order to assign or retrieve a value to a variable referenced by a pointer, you need to dereference it.
What your code is doing is casting 10 into pointer to int (which is the memory address where the actual int resides).
addresses p and c may be larger than int.
The problem on some platforms you need
p = (int*) (long) 10;
See GLIB documentation on type conversion macros.
And for the people who might not find a use for this type of expressions, it is possible to return data inside pointer value returning functions. You can find real-world examples, where this case it is better to use this idiom, instead of allocating a new integer on the heap, and return it back - poor performance, memory fragmentation, just ugly.
You're assigning values (10 and 20) to the pointers which obviously is a potential problem if you try to read the data at those addresses. Casting the pointer to an integer is also really ugly. And your main function does not have a return statement. That is just a few things.
there is more or less everything wrong with it:
int *p,*c;
p=(int*)10;
c=(int*)20;
afterwards p is pointing to memory address 10
afterwards c is pointing to memory address 20
This doesn't look very intentional.
And I suppose that the whole program will simply crash.