Casting (double *) to (double **) allowed? - c++

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.

Related

Why do I get invalid conversion from int** to const int**? [duplicate]

I have a function that receives float** as an argument, and I tried to change it to take const float**.
The compiler (g++) didn't like it and issued :
invalid conversion from ‘float**’ to ‘const float**’
this makes no sense to me, I know (and verified) that I can pass char* to a function that takes const char*, so why not with const float**?
See Why am I getting an error converting a Foo** → const Foo**?
Because converting Foo** → const Foo** would be invalid and dangerous ... The reason the conversion from Foo** → const Foo** is dangerous is that it would let you silently and accidentally modify a const Foo object without a cast
The reference goes on to give an example of how such an implicit conversion could allow me one to modify a const object without a cast.
This is a very tricky restriction. It is related to the aliasing rules of the language. Take a look at what the standards say, because I have faced this once before:
(Page 61)
[Note: if a program could assign a
pointer of type T** to a pointer of
type const T** (that is, if line //1
below was allowed), a program could
inadvertently modify a const object
(as it is done on line //2). For
example,
int main() {
const char c = 'c';
char* pc;
const char** pcc = &pc; //1: not allowed
*pcc = &c;
*pc = 'C'; //2: modifies a const object
}
—end note]
Other anwers have detailled why this is an error in C++.
Let me address the question behind your question. You wanted to state, in the interface of your function, that your function will not modify float values contained in the array. Nice intention, and enables that your function is called with const float ** arrays. The question behind your question would be, how to achieve this without resolving to ugly casts.
The correct way to achieve what you wanted is to change the type of your function parameter to const float * const *.
The additional const between the stars assures the compiler that your method will not try to store pointers to const float in the array, since this type declares that the pointer values are also const.
You can now call this function with float ** (which was the example in your question), const float **, and const float * const * arguments.
If you converted the parameter to const float** you could then store a const float* at the memory location where the parameter points to. But the calling function thinks that this memory location is supposed to contain a non-const float* and might later try to change this pointed-to float.
Therefore you cannot cast a float** to a const float**, it would allow you to store pointers to constants in locations where pointers to mutable values are expected.
For more details see the C++ FAQ Lite.

Casting with pointer C++

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

What is the (double **) in front of a malloc mean?

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

C++: can't static_cast from double* to int*

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)

Why am I getting an error converting a ‘float**’ to ‘const float**’?

I have a function that receives float** as an argument, and I tried to change it to take const float**.
The compiler (g++) didn't like it and issued :
invalid conversion from ‘float**’ to ‘const float**’
this makes no sense to me, I know (and verified) that I can pass char* to a function that takes const char*, so why not with const float**?
See Why am I getting an error converting a Foo** → const Foo**?
Because converting Foo** → const Foo** would be invalid and dangerous ... The reason the conversion from Foo** → const Foo** is dangerous is that it would let you silently and accidentally modify a const Foo object without a cast
The reference goes on to give an example of how such an implicit conversion could allow me one to modify a const object without a cast.
This is a very tricky restriction. It is related to the aliasing rules of the language. Take a look at what the standards say, because I have faced this once before:
(Page 61)
[Note: if a program could assign a
pointer of type T** to a pointer of
type const T** (that is, if line //1
below was allowed), a program could
inadvertently modify a const object
(as it is done on line //2). For
example,
int main() {
const char c = 'c';
char* pc;
const char** pcc = &pc; //1: not allowed
*pcc = &c;
*pc = 'C'; //2: modifies a const object
}
—end note]
Other anwers have detailled why this is an error in C++.
Let me address the question behind your question. You wanted to state, in the interface of your function, that your function will not modify float values contained in the array. Nice intention, and enables that your function is called with const float ** arrays. The question behind your question would be, how to achieve this without resolving to ugly casts.
The correct way to achieve what you wanted is to change the type of your function parameter to const float * const *.
The additional const between the stars assures the compiler that your method will not try to store pointers to const float in the array, since this type declares that the pointer values are also const.
You can now call this function with float ** (which was the example in your question), const float **, and const float * const * arguments.
If you converted the parameter to const float** you could then store a const float* at the memory location where the parameter points to. But the calling function thinks that this memory location is supposed to contain a non-const float* and might later try to change this pointed-to float.
Therefore you cannot cast a float** to a const float**, it would allow you to store pointers to constants in locations where pointers to mutable values are expected.
For more details see the C++ FAQ Lite.