Say I have an object:
void *tmpValue;
and say I know that tmpValue points to a double.
A way to cast this into a double is to do the following:
double* dblPtr = (double*) tmpValue;
double dbl = *dblPtr;
But why does a direct casting from void* to double not work?
double dbl = (double) tmpValue; //error: "cannot convert from 'void*' to 'double'
Thanks in advance.
Interpreting a pointer (a memory address) as a floating-point value is not a sensible operation, and it probably fails on your platform because void * and double are not even the same size.
What you want to do is interpret the pointer as double * and dereference that double * pointer, as in your second code snippet.
You can do this in one line:
double dbl = *(double *)tmpValue;
But, hey, this is C++. Better to do
double dbl = *static_cast<double *>(tmpValue);
You can't cast from a pointer type to double. Recall that pointer type is essentially a memory address (typically 4 bytes containing location information of the data on the memory). Hence you can cast pointer type to integer, but casting to double wouldn't make sense.
When you cast the void* pointer into double* pointer type, you are essentially saying "this is now an address of a double rather than an address of void*"
If you want to get the value as double in one liner nevertheless, you can do
double dbl = *( (double*) tmpValue );
double dbl = *(double*)tmpValue
dereference the pointer and cast ist value
Related
I am trying to store the memory address in a double pointer and cout the value at that memory address but getting errors.
below is the code i am trying to compile:
struct doubleValue{
double a;
};
int main(){
doubleValue *DBL = new doubleValue;
DBL->a=15;
// now I want to store the address of DBL->a in a double pointer and print out the value of double pointer.
double &doubelPtr = &DBL->a;
cout<< *doubelPtr; // this value should be 15
}
If I run the above code then I get a compiler error "error: invalid initialization of non-const reference of type 'double&' from an rvalue of type 'double*'
double &doubelPtr = &DBL->a;
^"
Can somebody help me to correct this code? Thanks!
You are erroneously using the reference operator here:
double &doubelPtr = &DBL->a;
You should just declare a pointer and assign the address to it.
double *doubelPtr = &DBL->a;
The above uses the address-of operator. I know it's confusing that both operators (reference and address) use the same symbol &, but that's how it is.
However, I'm curious as to why you need to do this? Is it because you're calling a function that requires a pointer to double? If so, there is no need to do the roundabout way of declaring a pointer to double and assigning to it. Just pass the address of the double to the function.
double &doubelPtr should be double *doubelPtr
This is a case of reference vs. pointer;
double &doublePtr
is a reference, not an address; try doing this with
double *doublePtr
General syntax of pointer declaration: data-type *pointer_name;
A pointer is a variable whose value is the address of another variable, i.e., direct address of the memory location. Like any variable or constant, you must declare a pointer before you can use it to store any variable address. The data type of pointer must be same as the variable, which the pointer is pointing.
Why is it important that a pointer variable should contain the address of a variable of the same data type?
As a pointer has nothing to do with the value of another variable, why can't an integer pointer have the address of float data type variable?
Correct form:
int a = 10 ;
int *ptr = &a ;
ERROR, type mismatch
float a;
int *ptr; ptr = &a;
Because when you increase a pointer like
ptr++;
it will point to an address that is one multiplied with the size of the data type. If you do
ptr+=2;
and the data type is occupying 4 bytes which would be the case if the pointer was declared as
float *ptr;
the pointer will increase with 8 byte positions.
Before answering that, let me ask you, if it were valid, what would you do with such a pointer?
Suppose you have (inside a function)
float a;
int *ptr; ptr = &a;
*p = 1;
++*p;
return *p;
In such a case, there is no reason at all not to just use an int variable if it's an int you want.
Suppose you have (inside a function)
float a;
int *ptr; ptr = &a;
a = 3.14;
++*p;
return a;
In this sort of object aliasing, there can be a use, but allowing constructions like this is a pain for compilers. Compilers are free to assume, and some do assume, that the modification of *p has no effect on the value of a, so still return 3.14 unmodified;
If the latter case is something you're looking for, you can use union, which both makes your code clearer to other readers, and makes your code clearer to the compiler:
union {
float f;
int i;
} u;
u.f = 3.14;
++u.i;
return u.f;
So, to answer: it's to prevent you from shooting yourself in the foot. It's not allowed because there is no way such a pointer is useful. The one case where it could be useful is actually a case where it doesn't work, and there is another language construct that does handle it, and handles it correctly.
There is also the simple matter of dereferencing the pointer.
something = *pointer;
How much data should be read when the pointer is dereferenced? The compiler must know the data type in order to perform operations on the data like fetch, add, etc.
It's a safety feature. A pointer of one type pointing to a variable of another is a recipe for disaster; it has almost no legitimate purpose and almost anything you do with it is dangerous, especially if the types are of different sizes.
You can override this feature by means of casting. If you do so, you can no longer claim that you didn't know you were doing something dangerous.
It is possible for pointers to point to any data type: that's exactly what void pointers are for. You can use a void * to point to any data type1, and then you can get the original pointer back.
float f = 1.0f;
int i = 12;
void *p = &f;
p = &i;
Of course, you can't dereference a void pointer without first casting it back to the correct pointer type. It is up to you to ensure that the pointer type is correct.
// In C, this is valid: implicit conversions to void * and back.
float f = 1.0f;
void *p = &f;
float *fp = p;
printf("*fp = %f\n", *fp);
// In C++, you have to use a cast:
float *fp = static_cast<float *>(p);
Void pointers have limitations: you cannot dereference them, and you cannot do any pointer arithmetic.
1: Function pointers should not be cast to void *.
Lets understand it with an example.
int main()
{
char i = 8;
int *ptr = &i;
printf("Value of i = %d", *ptr);
return 0;
}
Ans: It will print some garbage because it dereferenced 4 byte in memory.
so if you do char *ptr = &i;, it will dereference 1 byte and so on..
It will give correct answer.
Because I followed a discussion where was told "Aliasing through incompatible pointer types is undefined behavior" (e.g. double d; int *p = (int *)&d; following question:
Is it allowed to cast an (double *) to (double **), e.g. double *d1; double **d2 = &d2 and using syntax like d2[0][y] expecting to be the same as d1[y]?
I know that it is not exactly aliasing through incompatible pointer types, but however I am not sure. Background is that I want to have a function which operates on 2-dimensional arrays (= images) but I want to be able to pass only a row or column of an image.
double** is incompatible with double*. The conversion is legal, but the only thing you can do with the results is cast it back. This seems more or less obvious: on a 32 bit machine, a double* won't even have the same size as a double.
But your example doesn't convert a double* to double**. It creates a new double**, which points to the double*. This is fine.
Is it allowed to cast an (double ) to (double *), e.g. double *d1; double **d2 = &d2 and using syntax like d2[0][y] expecting to be the same as d1[y]?
Of course not, and it won't even compile.
But if you meant:
double *d1;
double **d2 = &d2;
then yes, the above is perfectly valid and since d2[0][y] can be seen as (*d2)[y], there's really no problem at all.
Finally, remember that in the above code, you are not casting anything: &d2 is already of type double**. If you have to cast something, please use C++ style casts (static_cast, dynamic_cast, reinterpret_cast, etc..) and not C style casts.
for example in this code:
double **Data, *DataT;
Data = (double **)malloc(3*sizeof(double *)+3*12*sizeof(double));
I just read that malloc allocates memory from the heap. But i could not find what that (double **) meant in front of the malloc.
There is a line of code directly after this as well that i have seen this in.
for (i = 0, DataT = (double *)(Data+3); i < 3; i++, DataT += 12)
Here there is a (double *) in front of Data+3
Could you please explain to me what that does?
Thank you
malloc() returns type void *, while your pointer is of type double * or double **. The operator before malloc - looking like (type) - is the type conversion operator, needed to convert malloc's return value to the type of the pointer you are using.
(double**) is a cast. it says that the result of the malloc is changed to double**.
malloc returns void* according to the standard.
so it is casted to double** to be the same nature of data : double**.
but in C, there is no need to the cat because void * is casted implicitly. so you can write directly :
Data = malloc(3*sizeof(double *)+3*12*sizeof(double));
as your question is for C++, which is compatible with C malloc, you have to put the cast : (double**).
so you can use malloc and the cast if you have a code that you want to use in programs in C and in C++. else, use new and delete...
It's a type cast. The rules for its syntax and usage should be a part of any C primer. The definitive book for this kind of thing is the one by Kernighan and Ritchie.
It means "pointer to a pointer".
The (double **) is a casting operator. It casts the void pointer returned by malloc to a pointer to pointer to double.
It's a pointer to a pointer. e.g. a double dereference.
c -> some memory address
*c -> whatever is at the memory address stored in c
**c -> whatever is at the memory address stored in *c
The (double**) and (double*) are what are known as C style casts. These make whatever type is after them into the type inside the parentheses.
The first C style cast is turning the return type of malloc into double** so it can be stored in the double** variable.
The second cast is turning it into a double*, so it can be dereferenced correctly.
double** means that you're allocating a pointer to a pointer of a double
When I try to use a static_cast to cast a double* to an int*, I get the following error:
invalid static_cast from type ‘double*’ to type ‘int*’
Here is the code:
#include <iostream>
int main()
{
double* p = new double(2);
int* r;
r=static_cast<int*>(p);
std::cout << *r << std::endl;
}
I understand that there would be problems converting between a double and an int, but why is there a problem converting between a double* and an int*?
You should use reinterpret_cast for casting pointers, i.e.
r = reinterpret_cast<int*>(p);
Of course this makes no sense,
unless you want take a int-level look at a double! You'll get some weird output and I don't think this is what you intended. If you want to cast the value pointed to by p to an int then,
*r = static_cast<int>(*p);
Also, r is not allocated so you can do one of the following:
int *r = new int(0);
*r = static_cast<int>(*p);
std::cout << *r << std::endl;
Or
int r = 0;
r = static_cast<int>(*p);
std::cout << r << std::endl;
Aside from being pointers, double* and int* have nothing in common. You could say the same thing for Foo* and Bar* pointer types to any dissimilar structures.
static_cast means that a pointer of the source type can be used as a pointer of the destination type, which requires a subtype relationship.
Floating point-to-integer conversion is supported, so int a = static_cast<int>(5.2) is fine. However, it's a conversion - the underlying data types are completely incompatible. What you're asking is for the runtime to convert a pointer to an 8-byte structure to a pointer to a 4-byte structure, which it can't do in any meaningful way.
That having been said, if you really want to interpret your double as an integer, int* r = reinterpret_cast<int*>(p) will work fine.
You can convert between a double and an int with static_cast<>, but not between pointers to different types. You can convert any pointer type to or from void * with static_cast<>.
The rationale may be that int * and double * are often effectively arrays, and the implementation doesn't know how big the array is.
Because you used double * instead of double
The * after it means that you are declaring a pointer, which is vastly different from a regular double.
C++ can not safely static_cast a pointer to a different type of pointer like that.
If you are wanting to do this kinda thing, you must first dereference the variable.
r=new int(static_cast<int>(*p));
You must use new because a double and an integer can not reside in the same memory space(sanely)