#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])
Related
bool subsetSum(int arr[], const int &n, const int &sum)
{
bool T[n + 1][sum + 1];
}
The above code is used to generate an 2d Boolean type array in subsetSum, but the compiler says both "n" and "sum" must be constant. How can I create an 2d array in my function just like ordinary stack variable like “double” and “int”?
Declaring an array like you are atempting is not standard C++. The sizes used to declare the array must be known at compile time. Hence, the compiler reports that as an error. Some compiles support variable length arrays (VLAs) as an extension but they are not standard C++.
For dynamic arrays like that, use std::vector.
std::vector<std::vector<bool>> T(n+1, std::vector<bool>(sum+1));
It takes away need to deal with dynamic memory allocation and deallocation from user code.
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.
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.
There is a problem when I want to define a complex array:
#include<complex.h>
int main(){
int matrix=1000;
std::complex<double> y[matrix];
}
The error is "Variable length array of non-POD element type 'std::complex'
Is there something wrong with the definition of array here?
This kind of array only works with a length that is a constant expression, i.e. the length must be known at compile time.
To get a array of variable length, use an std::vector<std::complex<double>> y (matrix);
You should use std::vector (or std::array in some cases) over C-style arrays anyway.
You can't statically allocate a C++ array with size being a regular variable, since the value of matrix is not known until the program is executed. Try dynamically allocating your array:
std::complex<double> y = new std::complex<double>[matrix]
When you are doing using it, call:
delete[] y
The size of arrays must be know at compile time. It must be a constant expression. The value of matrix is only known at runtime. You must make matrix a constant to work.
const int matrix=1000;
The other way around is to use a vector whose size is variable and is initialized at runtime.
int matrix=1000;
std::vector<std::complex<double>> y(matrix);
C++ doesn't allow variable length arrays, either do it dynamically or use a vector.
Your compiler thinks that you are declaring a variable-length array, since matrix is non-const. Just make it constant and things should work:
const int matrix = 1000;
std::complex<double> y[matrix];
The error stems from the fact that variable-length arrays are only allowed for "dumb" data types, e.g. int/char/void* and structs, but not classes like std::complex.
When a multidimensional array is passed to a function, why does C++ require all but the first dimension to be specified in parameter li
A better way to ask this is to ask why C++ doesn't require the first dimension to be specified.
The reason is that for all arrays, you can't pass arrays by value to a function. If you try to declare a function taking an array the compiler will adjust the declaration to the corresponding pointer type.
This means that it doesn't matter what dimension you specify as the dimension doesn't form part of the function signature.
For example, these all declare exactly the same function.
void f(int *p);
void f(int p[]);
void f(int p[10]);
void f(int p[100]);
When navigating the array pointed to by p in the function, the only information that the copmiler needs is the size of the array elements, i.e. sizeof(int) in this case.
For more complex arrays exactly the same holds. These are all the same:
void g(Type p[][10][20]);
void g(Type (*p)[10][20]);
void g(Type p[10][10][20]);
void g(Type p[99][10][20]);
But these are all different from:
void g(Type p[][5][20]);
because adjusting the dimension of anything other than the outer array dimension affects the size of (at least) the outer array's elements meaning that the pointer arithmetic for navigating the array would have to change.
For example int a[n][m] is an array whose type is an int array of length m. In other words, the length of array is part of its type. And as for all function parameters, compiler need to know its type.
There is no such thing as multidimensional array in c++. It is just a syntax which looks like it. In int a[4] and int b[5] a and b are different types.
If you refer to static allocation, this is simple.
Because the blocks of memory are contiguous which means that the memory cells are one after each other and the compiler knows where the next cell is in memory.
For unidimensional array in memory looks like this:
http://cplusplus.com/doc/tutorial/arrays/arrays3.gif
For bidimensional array in memory looks like this:
http://i.msdn.microsoft.com/dynimg/IC506192.png
In short: The compiler doesn't need the dimension, because a array decays to a pointer. But any additional dimension is needed by the compiler, to calculate the correct location in memory.
At first you need to know that an array in C/C++ is a linear continuous object in memory. Which is very efficient.
Because an array in C/C++ is a linear continuous object in memory, an array will decay to a pointer. Copying the complete array will be a waste of time and memory and is not requiered. A pointer is anything needed to go through the array. To go through the array you can take the increment-operator or any calculation which evaluates to a valid address in the array. You can set a delimiter in the array itself i.e. '\0' in a String, or pass the length to the function seperatley to tell your code where the end of the array is.
With multi-dimensional arrays the thing is a little bit more complicated. A multi-dimesional array is still only a linear continuous object in the memory! But the compiler needs the information about the additional dimensions to calculate to correct position in memory, imagine the following:
char array[10][10]; // 0 - 99
correct:
// formal argument tells your compiler, that each column is 10 elements long
funca(int array[10][10]) {
// access to element 25 (2 * 10 + 4, the 10 is known through your formal argument, remember that an array is null based)
array[2][3] = 'x';
}
wrong:
// formal argument tells your compiler, that ech colum is 5 elements long
funcb(int array[10][5]) {
// access to element 15 (2 * 5 * + 4, the 5 is known through your formal argument, remember that an array is null based)
array[2][3] = 'x';
}
A note (or warning):
Arrays in Java, especiallay (irregular) multi-dimensional arrays are completely different.