int n,q;
cin>>n>>q;
int** seq=new int* [n]; // what is the meaning of this ?
I have been trying to understand this array declaration for half an hour but the
int* [n] is really confusing me a lot.
Is there a more convenient way to write this declaration ?
How can I have such type of declaration in cpp ?
Is there a more convenient way to write this declaration ?
The idiomatic way to declare that pointer array in c++ would be
int n,q;
cin>>n>>q;
std::vector<int*> seq(n);
Though it's questionable why int* pointers need to be stored in the array.
A int* is a pointer (I assume you know those).
So int*[n] is an array of length n containing pointers on integers.
What confuses people most, is that variables containing arrays actually are pointers in C++. Because of that, the variable's type, we store int*[n] to, has to be int**. The pointer points at the first element of the array, and e.g. seq[2] would be compiled into *(seq+2). A array is not an object but a construct in memory the computer doesn't know about at runtime.
Related
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
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.
#include<stdio.h>
using namespace std;
void fun(int** a){}
int main()
{
int n;
scanf("%d",&n);
int a[n][n];
fun(a);
return 0;
}
Getting this error in C++, but it is working fine in C
but working for typecasted to (void*)a
and then converting to array=(int**)a:
test_.cpp:9:8: error: cannot convert
‘int (*)[(((unsigned int)(((int)n) + -0x00000000000000001)) + 1)]’
to ‘int**’ for argument ‘1’ to ‘void fun(int**)’
tried to pass a[][size] but size is not known
Double arrays do NOT convert to double pointers.
Pass a double array to your function like so:
void fun(int arr[][5]);
Now it will work.
There are a couple of problems with your code. One is in C, the other, C++.
The C problem:
Even in C, your multidimensional array int a[n][n] does not convert to an int**. There's a huge difference between ragged (or jagged) multidimensional arrays and contiguous multidimensional arrays. Ragged arrays are declared and allocated as
int ** jagged_array
A jagged array declared in this style can obviously be passed as an int** argument to some function; there's no conversion involved. With this type of array, the programmer must allocate (and eventually free) storage for an array of int* pointers to each of the rows in the array and must also allocate (and eventually free) storage for each of the array's rows.
int * jagged_array[size_spec].
A jagged array declared in this style can also be passed as an int** argument to some function because of the way arrays decay to pointers in C (and C++). With this type of array, the programmer must allocate (and eventually free) storage for each of the array's rows.
Note that in both forms, there is an explicit place in memory for the int* pointers that point to the zeroth elements of the rows of the array. That is not the case with multidimensional arrays. A pointer to a row in a multidimensional array is computed, not stored. A multidimensional array declared as int a[n][n] cannot decay to an int**. It instead decays into an int*[n]. In C, a function that receives a variable length multidimensional array such as your int a[n][n] should be declared as <return_type> fund (int n, int vla[n][n]). (The array argument could also be specified as vla[][n]; the outer dimension is not needed.)
The C++ problem:
You are using variable length arrays. C++ does not support that C99 concept. That concept didn't exist in C with the original 1998 version of C++. The 2003 C++ standard was a minor revision to the 1998 C++ standard, so it didn't jump to C99. The authors of the most recent C++ standard, C++11, explicitly rejected supporting those C99 variable length arrays. You can't use variable length arrays in C++, at least not portably.
When T[N][N] decays it turns into T*[N] for which there is no viable conversion when passing in the array.
You have to specify the second dimension size when passing 2D array to functions. Otherwise, compilers cannot do addressing on the 2D array elements without knowing the size of second dimension.
Use
f(a[][5])
came across the code shown below in a small C++ example:
int (*arr1)[ARRAY_SIZE];
int (*arr2)[ARRAY_SIZE];
int (*arr3)[ARRAY_SIZE];
then in the constructor of the class:
ParallelMultiply::ParallelMultiply(int mat1[ARRAY_SIZE][ARRAY_SIZE],
int mat2[ARRAY_SIZE][ARRAY_SIZE],
int result_mat[ARRAY_SIZE][ARRAY_SIZE]):arr1(mat1),
arr2(mat2),
arr3(result_mat)
{
}
here, ParallelMultiply is the class, mat1, mat2, result_mat are 2-D arrays, and ARRAY_SIZE is the defined array length. But How can arr1, arr2 and arr3 can be initialized with two dimensional arrays?? Please explain.
Thank you!!
You may be familiar with the way an array can decay to a pointer and then that pointer can be used like an array (as long as its actual extent is known).
When this sort of thing is done to a multidimensional array, you get a pointer to array with one less array bound. Then that pointer can be used like the multidimensional array.
So arr1[i][j] and mat1[i][j] are the same int and have the same address.
Note that since the class is copying only pointers to the 2D arrays, the user needs to make sure the lifetime of those array arguments is long enough. And any modifications made through the class will happen to the original arrays.
arr1, arr2 and arr3 are pointers. Each pointer pointing to an array of size ARRAY_SIZE.