I have a variable definition int (**ff)[4];, which is very bad looking. If I'm right (inferred from the fact that int (*f)[4]; is a pointer to an array of 4 int-s) this is a pointer to a pointer to an array of 4 int-s.
Now I have tried to initialize this thing but I had no success. Initializing f was simple (f = new int[5][4];), but the line ff = new int*[6][4]; is not working. Microsoft Visual Studio Community 2013 says in an error message that
a value of type "int *(*)[4]" cannot be assigned to an entity of type "int (**)[4]"
I have a very bad feeling that I really misunderstood something.
EDIT:
Sorry, that I didn't said it explicitly: What I wanted, is to allocate memory space for not only one, but for more pointers which later can point to an array of an array of 4 int-s. Of course I wanted this in one line without the help of any other definition, conversion etc.
I can (not) see this used only in this way:
int (*a)[4] = new int[6][4];
int (**ff)[4] = &a;
int (**ff)[4] means "a pointer to pointer to an array of four ints". This means we have to have int (*)[4] first - an lvalue, so we can take its address with operator&.
On the other hand, new int*[6][4]; allocates an array of pointers to an array of four pointers (the "outer" array decays). This is completely different type from the first one.
I had to help myself with cdecl.org on this one.
Edit:
I've just made this:
using PTR = int (*)[4];
int (**ff)[4] = new PTR; // hooray, a dynamically allocated pointer!
but can't figure a way without the type alias...
Actually, there is one: int (**ff)[4] = new (int (*)[4]), gathered from this Q&A. Don't forget that all you have now is a dynamically allocated uninitialized pointer.
A double pointer is a pointer to a pointer to get the obvious out of the way. That means that it will hold the memory address of a pointer, again obvious. That means you initialise your pointer and only then point your double pointer to it. Such as,
int* f[] = new int[4];
int** ff = &f;
Then to access this you can do,
(*ff)[1]
This will allow you to access the information stored in the dynamic array.
NOTE: leave the [] beside f empty if the size is not known at compile time which is the reason you should be doing it this way in the first place.
If you want to access elements of an array a[3][3] by pointer to pointer to array than you can do that by below code :
int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
int (*p)[3]=a;
int (**ff)[3]=&p;
To print it :
int i,j;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%d ",ff[0][i][j]);
}
printf("\n");
}
Alan,
I think the problem here is your initial assumption is incorrect.
*f[4] (or (*f)[4])
would actually be an array of 4 pointers to int, not a pointer to an
array of 4 ints. Then,
**ff[4]
would be a pointer to an array of 4 pointers to
int. I would recommend backing up a little, with this information in hand, and
trying it again. Also, an assignment to the
**ff
would be a single pointer, and
probably not an array, depending on how you are intending to use it.
Blake Mitchell
retired free lance programmer
Related
This question already has answers here:
Why am I being told that an array is a pointer? What is the relationship between arrays and pointers in C++?
(6 answers)
Closed 5 years ago.
I am trying to understand arrays and pointers in c++.
In a past project, I did. I created a pointer and then assigned that pointer to an array of the same type. I've read previous posts, though, that says you can't assign a pointer to an array. Also from the pointer, I was able to use the index to get a certain element (square brackets []).
So I was wondering if anyone could explain to me arrays and pointers in C++ and why something like this is possible, I've tried looking for it online, but haven't found anything.
Example,
#include <iostream>
using namespace std;
int main()
{
int *pointer = new int[10];
for (int i = 0; i < 10; i++)
{
pointer[i] = i;
}
for (int i = 0; i < 10; i++)
{
cout << pointer[i];
}
return 1;
}
The main difference between arrays and pointers is that they are completely different things.
As array is a collection of objects, which is laid out contiguously in memory. For example, int x[5] defines an array named x, which is a collection of 5 integers, laid out side by side in memory. Individual elements in the array may be accessed using "array syntax" of the form x[i] where i is an integral value with values between 0 and 4. (Other values of i will result in undefined behaviour).
A pointer is a variable which holds a value that is an address in memory. For example, int *p defines p as a pointer to an int, and it can be initialised with the address of a variable of type int. For example, p = &some_int causes p to contain the address of some_int. When that is done, the notation *p (called dereferencing) provides access to the pointed-to variable. For example, *p = 42 will set some_int to have the value 42.
You'll notice, in the description above, I have not used the word "pointer" in describing an array, nor have I used the word "array" to describe a pointer. They are completely different things.
However, they can be used in ways that makes them seem the same, because of a few rules in the language. Firstly, there is a conversion called the "array-to-pointer" conversion. Because of this, it is possible to do
int x[5];
int *p = x;
The initialisation of p actually works by using the array-to-pointer conversion. Because it is being used to initialise a pointer, the compiler implicitly converts x to a pointer, equal to the address of x[0]. To do this explicitly (without the compiler silently and sneakily doing a conversion) you could have written
int *p = &x[0];
and got exactly the same effect. Either way, the assignment *p = 42 will subsequently have the effect of assigning x[0] to 42.
That suggests there is a relationship between expressions involving pointers and expressions involving (the name of) arrays. If p is equal to &x[0], then
p + i is equivalent to &x[i]; AND
*(p + i) is equivalent to x[i].
The language rules of C and C++ make these relationships symmetric, so (look carefully here)
x + i is equivalent to &x[i]; AND
*(x + i) is equivalent to x[i]
and, with pointers
p + i is equivalent to &p[i]; AND
*(p + i) is equivalent to p[i]
Which basically means that pointer syntax can be used to work with arrays (thanks to the pointer-to-array conversion) AND array syntax can be used to work with pointers.
Really bad textbooks then go on from this and conclude that pointers are arrays and that arrays are pointers. But they are not. If you find textbooks which say such things, burn them. Arrays and pointers are different things entirely. What we have here is a syntactic equivalence - even though arrays and pointers are different things entirely, they can be worked on using the same syntax.
One of the differences - where the syntactic equivalence does not apply - is that arrays cannot be reassigned. For example;
int x[5];
int y[5];
int *p = y; // OK - pointer to array conversion
x = y; // error since x is an array
x = p; // error since x is an array
The last two statements will be diagnosed by a C or C++ compiler as an error, because x is an array.
Your example
int *pointer = new int[10];
is a little different again. pointer is still not an array. It is a pointer, initialised with a "new expression", which dynamically allocates an array of 10 integers. But because of the syntactic equivalence of pointers and arrays, pointer can be treated syntactically AS IF it is an array of 10 elements.
Note: the above is concerned with raw arrays. The C++ standard library also has a type named std::array which is a data structure which contains an array, but behaves somewhat differently than described here.
a pointer in reality is a variable which keeps an address of a memory it points to. The memory itself can be allocated by one of the heap management functions like 'malloc' or 'new' or some others. So, in general you ask the function to allocate a certain amount of memory and return its address. You keep the latter as the pointer to it in a variable.
Arrays in 'c++/c' are contiguous chunks of memory. So, there is no difference between allocating 40 bytes or 10 integers in the array (assuming that an int is 4 byte long).
'c/c++' also understand the type of the data which the allocated memory contains. The languages provide a feature named 'pointer arithmetic'. This actually means that you can add to a pointer or subtract from it. The language will factor the values by the size of the type. I.e.
int *a = new ...
int b = *(a+4);
In the above case value of 'b' will be the same as the value saved in memory 'a' with offset of 16 bytes.
The above is very similar to the array indexing arithmetic and the language allow you to use the array indexing instead of the above:
b = a[4];
So, in this sense both worlds intersect and you can interchangeably use either pointer arithmetic or array arithmetic in the language.
Arrays do not have to be allocated on the heap as well as the pointers do hot have to address the heap only. You can have an array allocated on stack or in the global scope and have a pointer to it:
int myarray[10];
int *pointer = myarray;
How you can apply either the pointer arithmetic or array arithmetic to the pointer. the following are equivalent (if you did not advance the pointer)
myarray[3]
pointer[3]
*(pointer + 3)
Hope it clarifies the issue for you.
From wikipedia:
A pointer references a location in memory, and obtaining the value
stored at that location is known as dereferencing the pointer
Arrays are the contiguous memory locations and their location in memory is referenced by a pointer.
int *pointer = new int[10];
for (int i = 0; i < 10; i++)
{
pointer[i] = i;
}
the code above is actually accesses pointer + i * sizeof(int) thanks to operator[] (assume variable pointer is an integer or smth like that, no pointer arithmetic here.)
For example, can you explain what would happen in the following code?
class Vector{
int v[3];
Vector(int *x);//parameterized constructor created
};
Vector::Vector(int *x)//definition of the parameterized constructor
{
for (int i=0;i<size;i++)
v[i]=x[i];//what happens here?? why did we take pointer as arguement?
}
From my understanding, by putting v[i]=x[i] we created a new array in which all elements of v are now in x. Why did this require a pointer argument? Couldn't it have been done with a reference &?
This goes back to older style C habits, when you can use a pointer as an array, by "indexing" it's elements.
Taken from: https://en.wikibooks.org/wiki/C_Programming/Pointers_and_arrays
A variable declared as an array of some type acts as a pointer to that type. When used by itself, it points to the first element of the array.
A pointer can be indexed like an array name.
However, a few notes:
v[i]=x[i] we created a new array
No, you did not create a new array here, the array was already created when the body of the constructor got executed. What happens here is that TO the value v[i] we will assign the value of: *(x + i) ie. the ith. element from the address x points to. Unless you know how x was created and initialized this is pretty dangerous code. Just imagine you can call this method with the address of a single int. I suppose, size is 3 or less, otherwise this code has serious security issues.
You always should check for null pointers, before trying to access the value they point to.
You can pass in the array by reference if you know the size of x at compile time:
Vector(int (&x)[3]);
If you don't know the size at compile time then what you're doing goes from being unsafe code, to blatantly wrong code.
Another option is to use std::array if you know the size at compile time, and std::vector if you don't.
Just to add a bit to previous answers, the indexing operator [] actually dereferences a pointer and shifts it by index*sizeof(type) at the same time. The same relates to declaration of an array. Say, if you declare int a[1]; this means that a is now a pointer to int, i.e. int*. So if you wanted to pass it to a function as an argument, you would need to specify its type as int*.
reading this question: What is the difference between int* x[n][m] and int (*x) [n][m]?
the correct reply stated this:
int arr[2][3];
int (*p1)[2][3] = &arr; // arr decays to int(*)[3], so we need to take the address
int (*p2)[2][3] = new int[42][2][3]; // allocate 42 arrays dynamically
the comment in that last line says it allocates 42 new arrays.
how does that work? can someone explain that to me?
thanks!
i would reply on that question, but i can't, so new question it is (:
new int[3] allocates 3 integers. Now new int[2][3] allocates 2 arrays, each of length 3 integers. Extending this further, new int[42][2][2] allocates 42 arrays, each of length 2 arrays, each of which in turn is, of length 2 integers. Declarations are really a recursive idea.
Allright, class time.
C++ Multidementional arrays vs. Jagged array
A multidemenional array (in C++) is a block of contiguous memory. It allocates the full number of elements, all in a line, and then access them by combining the index accessors. In essense. If I have an array defined by int x[2][3], it essentially turns x[i][j] into (&x[0][0]+i*3)[j].
sizoef(int[2][3])==24 (4bytes/int*2*3)
This type of array is often called a "static" array, because the size of the array must be allocated at compile time.
Note that the first size is irrelevent to this lookup. This makes it so that, when REFERENCING this type of array, we can exclude the smallest size from the type. This makes is so that both the functions below are valid and can work on the array x declared above:
int foo(int y[2][3]){ return y[1][1];}
int bar(int y[][3]){ return y[1][1];}
Note in this context, sizeof(y)==sizeof(void*), but that is a different problem all together.
The typeing convention for static arrays behaves differently than your used to. Part of the type information comes AFTER the variable declaration. This actually persists in typedefs as well:
typedef int a[4][20];
typedef int b[][20];
If you wanted to take the address of such a value type, then what you need to declare the pointer to this array type. That can be done with:
int (*xptr)[2][3] = &x;
The int (*var)[...] says that var is a pointer to a int[2][3].
When people say C++ arrays are pointers, they are NOT refering to this type of array: the array is a little more compilicated than a pointer here, though we could flatten it into a 1D array.
A jagged array (or dynamic array) is a single block of contiguose memory that is allocated in a linear fashion. This type of array is often called dynamic because the size does NOT need to be known at compile time.
Dynamic arrays are allocated with new or malloc (though you should only use new in C++). These types of array are strictly pointers. When I say int* a=new int[4], I allocate 4 integers: thats it.
We achieve mutlidementionality here by crating jagged arrays, which are arrays of pointers. So for example:
int** a = new int*[2];
for (int i = 0; i < 2; i++) { a[i]=new int[3];}
What your code does
int arr[2][3];//
int (*p1)[2][3] = &arr; // arr decays to int(*)[3], so we need to take the address
int (*p2)[2][3] = new int[42][2][3]; // allocate a dynamic array (42 elements long) of int[2][3] (sizeof(int[2][3])==24, so this allocates 42*24 bytes!)
It essentially allocates 43 int[2][3] in a row. So it actually comes up with all contiguous memory (though why it needs to be dynamic and not static is beyond me).
Personally, my rule is multidementional arrays "confusing as hell" and only use them in a local context now, but to each their own.
I'm having trouble with c++ pointers. I have a pointer to array of pointers.
and the case is:
MyType *(*arr)[5];
MyType **a = arr;
the 2nd line gives an error. How can i take pointer to this array ?
The error says it all (include it in your question the next time).
You declare a pointer to array of five pointers to MyType. Then you try to assign it to pointer-to-pointer-to MyType. This is exactly what error message says:
IntelliSense: a value of type "MyType *(*)[5]" cannot be used to initialize an entity of type "int **"
Another suggestion is to tell, what you are trying to achieve. Though my explanation is technically correct, I doubt it will solve your actual problem.
int* arr[8]; // An array of int pointers.
int (*arr)[8]; // A pointer to an array of integers
Here arr is a pointer which points to an array of pointers. So if you want to take pointer to the array, use MyType **a=*(arr+i) where *(arr+i) is the i th array.
I know this might be a common question but I have tried to search but still cannot find a clear answer.
I have the following code:
int* f() {
int a[] = {1,2,3};
return a;
}
int main() {
int a[] = f(); // Error here
getch();
return 0;
}
This code produces the error message: "Cannot convert from 'int *' to 'int []'"
I found this quite strange because I have read that pointer and array are similar. For example, we can use a[i] instead of *(a + i).
Can anyone give me a clear explanation, please?
There are actually two errors in this code.
Firstly, you are returning the address of a temporary (the int array within f), so its contents are undefined after the function returns. Any attempt to access the memory pointed to by the returned pointer will cause undefined behaviour.
Secondly, there is no implicit conversion from pointers to array types in C++. They are similar, but not identical. Arrays can decay to pointers, but it doesn't work the other way round as information is lost on the way - a pointer just represents a memory address, while an array represents the address of a continuous region, typically with a particular size. Also you can't assign to arrays.
For example, we can use a[i] instead of *(a + i)
This, however, has little to do with the differences between arrays and pointers, it's just a syntactic rule for pointer types. As arrays decay to pointers, it works for arrays as well.
The type int[] doesn't actually exist.
When you define and initialize an array like
int a[] = {1,2,3};
the compiler counts the elements in the initializer and creates an array of the right size; in that case, it magically becomes:
int a[3] = {1,2,3};
int[] used as a parameter to a function, instead, it's just plain int *, i.e. a pointer to the first element of the array. No other information is carried with it, in particular nothing about the size is preserved. The same holds when you return a pointer
Notice that an array is not a pointer: a pointer can be changed to point to other stuff, while an array refers always to the same memory; a pointer does not know anything about how big is the space of memory it points to, while the size of an array is always known at compile time. The confusion arises from the fact that an array decays to a pointer to its first element in many circumstances, and passing it to a function/returning it from a function are some of these circumstances.
So, why doesn't your code work? There are two big errors:
You are trying to initialize an array with a pointer. We said that an int * doesn't carry any information about the size of the array. It's just a pointer to the first element. So the compiler cannot know how big a should be made to accomodate the stuff returned by f().
In f you are returning a pointer to a variable that is local to that function. This is wrong, because a pointer does not actually store the data, it only points to where the data is stored, i.e. in your case to the a local to f. Because that array is local to the function, it ceases to exist when the function exits (i.e. at the return).
This means that the pointer you are returning points to stuff that does not exist anymore; consider the code:
int * a = f();
This initialization works, and you can try to use a later in the function, but a will be pointing to the no-longer existent array of f; in the best case your program will crash (and you'll notice immediately that you've done something wrong), in the worst it will seem to work for some time, and then start giving strange results.
int * and int [] are similar but different.
int * is a real pointer, meanwhile int[] is an array reference ( a sort of "constant pointer" to the begin of the data) wich cannot be modified. So, a int * can be threated like a int [] but not viceversa.
You can use a[b] and*(a+b) interchangeably because that is exactly how a[b] is defined when one of a or b is a pointer and the other is of integer or enumeration type.
Note: This also means that expressions like 42[a] are perfectly legal. Human readers might object strongly, but the compiler won't bat an eye at this.