I'm having problems getting this to work,
class A {
public:
A(int n) {
a = n;
}
int getA() {
return a;
}
private:
int a;
};
int main(){
A* a[3];
A* b[3];
for (int i = 0; i < 3; ++i) {
a[i] = new A(i + 1);
}
void * pointer = a;
b = (A* [])pointer; // DOESNT WORK Apparently ISO C++ forbids casting to an array type ‘A* []’.
b = static_cast<A*[]>(pointer); // DOESN'T WORK invalid static_cast from type ‘void*’ to type ‘A* []’
return 0;
}
And i can't use generic types for what i need.
Thanks in advance.
Arrays are second-class citizen in C (and thus in C++). For example, you can't assign them. And it's hard to pass them to a function without them degrading to a pointer to their first element.
A pointer to an array's first element can for most purposes be used like the array - except you cannot use it to get the array's size.
When you write
void * pointer = a;
a is implicitly converted to a pointer to its first element, and that is then casted to void*.
From that, you cannot have the array back, but you can get the pointer to the first element:
A* b = static_cast<A*>(pointer);
(Note: casting between pointers to unrelated types requires a reinterpret_cast, except for casts to void* which are implicit and from void* to any other pointer, which can be done using a static_cast.)
Perhaps you mean to do
memcpy(b, (A**)pointer, sizeof b);
?
A static_cast version is also possible.
Related
I was writing a C++ function that takes int** as input and the function itself does not modify the data (i.e. matrix elements). So I decided to make the argument a const int** type (Is that an acceptable practice?). A sample code is like this:
void func1(const int* k) {
std::cout << *k << '\n';
}
void func2(const int** k) {
std::cout << **k << '\n';
}
int main() {
int m = 0;
int* p1 = &m;
func1(p1);
int** p2 = &p1;
func2((const int**)p2); // compilation error unless explicit type conversion
// func2(p2); /* [*] compilation error */
(**p2) += 1;
func1(p1);
func2((const int**)p2);
return 0;
}
My question is, when calling func2, I have to explicitly convert the double-pointer p2 to const int**, otherwise it gives the following error:
error: invalid conversion from ‘int**’ to ‘const int**’ [-fpermissive]
Whereas func1 has no such issue. I tested this with both g++ (10.2.0) on Cygwin and Intel's icpc. Could someone explain why the compiler behaves this way and what is a good practice in this situation?
In a sense, having a const int ** is saying "this pointer points to a pointer to an integer that won't be modified". The problem with implicitly casting an int ** to const int ** is that that promise is easy to mistakenly not keep. For example:
const int c = 1;
int *p1;
const int **p2 = &p1; /* implicit cast from int** to const int** */
*p2 = &c; /* change what the pointed-to pointer points to */
*p1 = 2; /* change a value pointed to by a const int** */
So the requirement for an explicit cast is to make you think about this, I guess.
Example adapted from here.
With multiple levels of pointers, a type is only more const-qualified if every level of pointer from the right has const added. This is for const-correctness reasons so that when you assign to the pointer, you can't accidentally assign a more const-qualified pointer at the "lower" levels of pointers when you have multiple pointers.
For example:
int *** * * * i;
int ***const*const*const* j = i;
// ^ All levels after this have to be const-qualified
This includes the left-most type, const int. So, if your data is not modified, you should have int const* const* k.
This is the case in C++ (as a qualification conversion), but this is still allowed implicitly in C because all pointers can be implicitly converted.
Because you cannot return int[] (or any array type for that matter) in c++, I have a function or two which instead return int*, which has made my existence rather difficult.
A function of my program requires that an array that I've been passing about between functions be copied and incremented around in various ways, and then the copy returned. The only way I've found to copy the data such that the original array is unaffected by changes in the copy, is copying each "member" at a time, e.g.
int* foo(int* a) {
int b[2] = {a[0], a[1]};
/* do unspeakable things to b */
return b;
}
Which is fine enough for this very specific case, but I'm sure isn't the most effective method, especially for large arrays.
Is there some type-casting wizardry or other method I can use to do this
more efficiently?
NOTE: I'm not asking if this is good practice, useful, in line with the Geneva convention, or safe very intentionally. I don't particularly care about that information at this moment, and if you absolutely must say it I'd rather it not be the body or opening of your answer.
Also, is the kerning around the T in NOTE super weird for anyone else?
EDIT: After actually using my "solution" I determined that I'm an idiot and should test things before spouting off about them.
int b[2];
int * c = b;
From cppreference implicit conversion:
Array to pointer conversion
An lvalue or rvalue of type "array of N T"
or "array of unknown bound of T" can be implicitly converted to a
prvalue of type "pointer to T".
That means that any array of type is implicitly converted to a pointer to type. The pointer points to the first member of the array, so c == &b[0]. Interestingly, the pointer to array is also equal to the pointer of the first element of the array &b == &b[0], but has a different type, ie:
int b[2];
int * c = b; // implicit conversion from array to pointer
int (*d)[2] = &b; // &b is a pointer to an array of 2 ints
int * e = &b[0]; // pointer to the first element
The function:
int* foo(int* a) {
int b[2] = {a[0], a[1]};
/* do unspeakable things to b */
return b;
}
Is very invalid, wrong, confusing and bad. The memory behind b is invalid after } function returns, so the pointer returned by the function is invalid and cannot be used.
Because you cannot return int[]
int[] is an array of unspecified size, you cannot do anything with it. Note that inside function parameter list int[] is implicitly converted into int*. So the following are exactly equivalent:
void f(int a[]);
void f(int *a);
or any array type for that matter) in c++
You can return std::array<int , 2>
std::array<int, 2> f() {
std::array<int, 2> ret;
return ret;
}
Note that this is highly inefficient. It needs to return 2 * sizeof(int) of data, which will get bigger with greater size. Returning a pointer to the first member of the array is only returning the pointer value, needs less space. Also note that std::array<int, 2> var = f(); will copy all array elements between f() returned value and var (without copy elision), so it's very inefficient.
I'm sure isn't the most effective method
In terms of speed, initializing each array member explicitly and returning a pointer to the first element of an array is the most efficient method. A proper compiler will generate fast instruction for that. But you say and then the copy returned - you have to create a copy in your function of the array, so you have to copy all array members between the original and the copy. There's no other way around.
Is there some type-casting wizardry or other method I can use to do this more efficiently?
Toss raw C array to the trash bin, and move to containers. Move to std::array<int, 2> if you know the size at compile time, and std::vector<int> if the size is unknown at compile time.
std::vector<int> foo(std::vector<int> a) {
std::vector<int> b{a};
return b;
}
Note that return b is ok here, as the std::vector<int> in itself stores a pointer to dynamically allocated memory. Memory allocated with new does not cease to exist after }, so you can return a pointer to it. If your compiler supports copy elision, the function should work fast. A faster version would be to use references.
void f(std::vector<int>& ret, std::vector<int> a) {
ret = a;
}
You can input both int array into a function and let the function do the copy for you like this:
bool CopyIntArray(int* pA, int cA, int* pB, int cB)
{
if (pA == NULL || cA == 0 || pB == NULL || cB == 0)
{
return false;
}
for (int i = 0; i < cA && i < cB; i++)
{
pB[i] = pA[i];
}
return true;
}
int main()
{
int x[10] = { 0,1,2,3,4,5,6,7,8,9 };
int y[10] = { 0 };
CopyIntArray(x, 10, y, 10);
return 0;
}
by the way
int* foo(int* a) {
int b[2] = {a[0], a[1]};
/* do unspeakable things to b */
return b;
}
b is destroyed when step out of the function scope, so your app would be dangerous when use a destroyed variable as the function output.
In the code below I am casting pointer type to reference pointer type in order to change the pointer to point somewhere else:
inline void SWAP_POINTERS(void*& p1,void*& p2)
{
void* temp = p1;
p1 = p2;
p2 = temp;
}
When I call the function I ge the following error:
note: candidate function not viable: no known conversion from 'int32_t *' (aka 'int *') to 'void *&' for 1st argument
Do I need to cast?
Why do I need to cast since it is void*?
Limitation: no templates.
calling the code like this:
unsigned int* a;
double* b;
SWAP_POINTERS(a,b);
1. You're probably breaking strict aliasing once you dereference one of the pointers after swapping.
unsigned int* a;
double* b;
SWAP_POINTERS(a,b);
Don't swap pointers which do not point to the same type however. (Note that char aliases other types but that is an exception.)
2. You cannot convert int* to void*& implicitly.
int* is implicitly convertible to void* but the conversion creates an rvalue which cannot be bound to an lvalue reference.
In order to use SWAP_POINTERS with the signature shown in the question, one would have to create lvalues of type void* first and pass those to SWAP_POINTERS.
Example:
int a{0}, b{1};
int * pa = &a;
void * vpa = pa;
int * pb = &b;
void * vpb = pb;
SWAP_POINTERS(vpa, vpb); // swaps vpa and vpb - OF COURSE :)
Please note that this doesn't solve the (probably inteded) swapping of (unrelated) pointers with minimal code. Its just an explanation of why the original code with void*& in place did not work when passing int* and how a call to the original function would have to look in order to be able to operate (on its function arguments...).
3. Swap pointers via std::swap
int a{0}, b{1};
int * pa = &a;
int * pb = &b;
std::swap(pa, pb);
This will do what you think you want, but it's totally NOT recommended. Templates (or std::swap) really are the right answer here.
First, define an inline function to take void **
inline void SWAP_POINTERS2(void** p1,void** p2)
{
void* temp = *p1;
*p1 = *p2;
*p2 = temp;
}
Then, define a macro to perform unpleasant casts.
#define SWAP_POINTERS(a,b) SWAP_POINTERS2((void **) &a, (void **) &b)
Or, if you prefer using static_cast:
#define SWAP_POINTERS(a,b) SWAP_POINTERS2(static_cast<void**>(static_cast<void *> (&a)), static_cast<void**>(static_cast<void *>(&b)))
Now this "works" to the extent that it compiles and does what you want. I have no idea how you'd then use the swapped pointers, of course...
unsigned int* a;
double* b;
SWAP_POINTERS(a,b);
What is the following code doing?
int g[] = {9,8};
int (*j) = g;
From my understanding its creating a pointer to an array of 2 ints.
But then why does this work:
int x = j[0];
and this not work:
int x = (*j)[0];
The parenthesis are superfluous in your example. The pointer doesn't care whether there's an array involved - it only knows that its pointing to an int
int g[] = {9,8};
int (*j) = g;
could also be rewritten as
int g[] = {9,8};
int *j = g;
which could also be rewritten as
int g[] = {9,8};
int *j = &g[0];
a pointer-to-an-array would look like
int g[] = {9,8};
int (*j)[2] = &g;
//Dereference 'j' and access array element zero
int n = (*j)[0];
There's a good read on pointer declarations (and how to grok them) at this link here: http://www.codeproject.com/Articles/7042/How-to-interpret-complex-C-C-declarations
int g[] = {9,8};
This declares an object of type int[2], and initializes its elements to {9,8}
int (*j) = g;
This declares an object of type int *, and initializes it with a pointer to the first element of g.
The fact that the second declaration initializes j with something other than g is pretty strange. C and C++ just have these weird rules about arrays, and this is one of them. Here the expression g is implicitly converted from an lvalue referring to the object g into an rvalue of type int* that points at the first element of g.
This conversion happens in several places. In fact it occurs when you do g[0]. The array index operator doesn't actually work on arrays, only on pointers. So the statement int x = j[0]; works because g[0] happens to do that same implicit conversion that was done when j was initialized.
A pointer to an array is declared like this
int (*k)[2];
and you're exactly right about how this would be used
int x = (*k)[0];
(note how "declaration follows use", i.e. the syntax for declaring a variable of a type mimics the syntax for using a variable of that type.)
However one doesn't typically use a pointer to an array. The whole purpose of the special rules around arrays is so that you can use a pointer to an array element as though it were an array. So idiomatic C generally doesn't care that arrays and pointers aren't the same thing, and the rules prevent you from doing much of anything useful directly with arrays. (for example you can't copy an array like: int g[2] = {1,2}; int h[2]; h = g;)
Examples:
void foo(int c[10]); // looks like we're taking an array by value.
// Wrong, the parameter type is 'adjusted' to be int*
int bar[3] = {1,2};
foo(bar); // compile error due to wrong types (int[3] vs. int[10])?
// No, compiles fine but you'll probably get undefined behavior at runtime
// if you want type checking, you can pass arrays by reference (or just use std::array):
void foo2(int (&c)[10]); // paramater type isn't 'adjusted'
foo2(bar); // compiler error, cannot convert int[3] to int (&)[10]
int baz()[10]; // returning an array by value?
// No, return types are prohibited from being an array.
int g[2] = {1,2};
int h[2] = g; // initializing the array? No, initializing an array requires {} syntax
h = g; // copying an array? No, assigning to arrays is prohibited
Because arrays are so inconsistent with the other types in C and C++ you should just avoid them. C++ has std::array that is much more consistent and you should use it when you need statically sized arrays. If you need dynamically sized arrays your first option is std::vector.
j[0]; dereferences a pointer to int, so its type is int.
(*j)[0] has no type. *j dereferences a pointer to an int, so it returns an int, and (*j)[0] attempts to dereference an int. It's like attempting int x = 8; x[0];.
For static_cast, Is it true that, unless there exist a built-in type conversion function, you cannot use static_cast to perform conversion. But you can do a reinterpret_cast for a type, considering the return type is valid.
int main()
{
WORD word;
HWND hwnd = static_cast<HWND>(word); // error
HWND hwnd = reinterpret_cast<HWND>(word); // ok, considering a valid handle is returned.
}
Do the explicit type conversions done with static_cast require a conversion function unlike reinterpret_cast?
reinterpret_cast just allows you to convert completely unrelated types. It just treats the chunk of memory as another type. So it is very unsafe to use it, since it just doesn't give you any compile or runtime errors but just causes (usually) crash
static_cast provides compile time check of validity of an cast. If an type cannot be treated as another type then static_cast gives you an compile time error when attempting an cast.
It does implicit conversions between types (such as int to float, or pointer to void*), and it can also call explicit conversion functions (or implicit ones).
So you can say that it can do the implicit casts for which there is an implicit conversion inbuilt function present. It is usually considered as replacement for c-style casting if that is the confusion.
The C++ casts make most sense when casting pointers and references.
Concrete examples
void foo (Base & b) {
if (b .is_a_Foo ())
static_cast <Foo &> (b) .bar ();
else
b .do_default_bar ();
dynamic_cast <Baz &> (b) .something (); // throws if invalid conversion
}
char data [4];
* reinterpret_cast <float *> (data) = 1.23;
The Windows API is a horrible hack from top to bottom -- in your example, reinterpret_cast is faithful to the original intent (and highlights it for the world to admire) and it basically means "throw away the type system and use the raw bits: trust me".
Basically static_cast allocates memory for compatible class size of destination type and fills it with what is possible, but without any checking that new object is complete. Let me give you an example:
class A {
public:
int a;
};
class B : public A {
public:
int c;
int b;
};
int main()
{
A *a = new A;
a->a = 5;
B *b = new B;
b->a = 6;
b->b = 7;
b->c = 8;
B* bb = static_cast<B*>(a);
A* aa = static_cast<A*>(b);
cout << bb->a << endl; // 5
cout << bb->b << endl; // scrap value from memory
// member b was not initialized, because it was not found in A
cout << aa->a << endl; // 6
return 0;
}
In your example static cast is invalid, because hwnd is void * and word is unsigned short. For c++ casts any type can be considered as a class;
reinterpret_cast works always. It is just a binary copy