Create 2D array using size from parameters in C++
I like a simple wrapper around a 1D vector:
#include <vector>
class Matrix
{
private:
size_t rows, columns;
std::vector<double> matrix;
public:
Matrix(size_t numrows, size_t numcols) :
rows(numrows), columns(numcols), matrix(rows * columns)
{
}
double & operator()(size_t row, size_t column)
{
return matrix[row * columns + column]; // note 2D coordinates are flattened to 1D
}
double operator()(size_t row, size_t column) const
{
return matrix[row * columns + column];
}
size_t getRows() const
{
return rows;
}
size_t getColumns() const
{
return columns;
}
};
Documentation for std::vector
Usage:
Matrix noiseMap(mapWidth, mapHeight);
C - Can I set the size of a multidimensional array in a function parameter list to something higher than its actual size?
For starters such a declaration of the function main
static void main()
is not standard.
The function should be declared like
int main( void )
If your compiler supports variable length arrays then you may declare the function like
static void fill_array( size_t rows, size_t cols, int ar[][cols] );
and pass a two-dimensional array of any sizes.
Here is a demonstrative program.
#include <stdio.h>
static void fill_array( size_t rows, size_t cols, int a[][cols] )
{
for ( size_t i = 0; i < rows; i++ )
{
for ( size_t j = 0; j < cols; j++ )
{
a[i][j] = i * cols + j;
}
}
}
int main(void)
{
size_t rows;
size_t cols;
printf( "Enter the number of rows: " );
scanf( "%zu", &rows );
printf( "Enter the number of columns: " );
scanf( "%zu", &cols );
int a[rows][cols];
fill_array( rows, cols, a );
for ( size_t i = 0; i < rows; i++ )
{
for ( size_t j = 0; j < cols; j++ )
{
printf( "%2d ", a[i][j] );
}
putchar( '\n' );
}
return 0;
}
Its output might look for example like
Enter the number of rows: 3
Enter the number of columns: 5
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
How to declare a 2D vector parameter which will accept any size?
For statically sized arrays, use std::array. For dynamically sized arrays use std::vector. Don't ever use raw C arrays unless some weird situation forces it on you.
If you need a multi dimensional array, you can of course use std::vector<std::vector<int>>
or similar for std::array
. This is easy and convenient since you can do myarray[row][column]
(and possibly good enough). But a better performing option is usually to just declare a 1D std::vector<int>
with a size of "dimension 1 * dimension 2" and then, when indexing into it, do myvector[row_number * size_of_row + column]
. Treating a 1D array as a 2D one is as easy as that and it is likely to perform better since it's friendlier to your CPUs prefetcher and cache hierarchy.
As for declaring a function to accept such arrays - it's straight forward. For example:
void f(const std::array<int, 666>& myarray);
void f(const std::array<std::array<int, 42>, 666>& myarray);
void f(const std::vector<int>& myarray);
void f(const std::vector<std::vector<int>>& myarray);
Why do we need to specify the column size when passing a 2D array as a parameter?
When it comes to describing parameters, arrays always decay into pointers to their first element.
When you pass an array declared as int Array[3]
to the function void foo(int array[])
, it decays into a pointer to the beginning of the array i.e. int *Array;
. Btw, you can describe a parameter as int array[3]
or int array[6]
or even int *array
- all these will be equivalent and you can pass any integer array without problems.
In case of arrays of arrays (2D arrays), it decays to a pointer to its first element as well, which happens to be a single dimensional array i.e. we get int (*Array)[3]
.
Specifying the size here is important. If it were not mandatory, there won't be any way for compiler to know how to deal with expression Array[2][1]
, for example.
To dereference that a compiler needs to compute the offset of the item we need in a contiguous block of memory (int Array[2][3]
is a contiguous block of integers), which should be easy for pointers. If a
is a pointer, then a[N]
is expanded as start_address_in_a + N * size_of_item_being_pointed_by_a
. In case of expression Array[2][1]
inside a function (we want to access this element) the Array
is a pointer to a single dimensional array and the same formula applies. The number of bytes in the last square bracket is required to find size_of_item_being_pointed_by_a
. If we had just Array[][]
it would be impossible to find it out and hence impossible to dereference an array element we need.
Without the size, pointers arithmetics wouldn't work for arrays of arrays. What address would Array + 2
produce: advance the address in Array
2 bytes ahead (wrong) or advance the pointer 3* sizeof(int) * 2
bytes ahead?
How do I pass a 2D array into a function with unknown size in C?
You can pass a multidimensional array with sizes based on other parameters:
void invertImg(int height, int width, unsigned char img[height][width])
{
...
A declaration for this function without parameter names would look like this:
void invertImg(int, int, unsigned char img[*][*]);
Then you can call the function like this:
invertImg(height, width, pixels);
How to pass two dimensional array of an unknown size to a function
Multi-dimensional arrays are not very well supported by the built-in components of C and C++. You can pass an N
-dimension array only when you know N-1
dimensions at compile time:
calculateDeterminantOfTheMatrix( int matrix[][123])
However, the standard library supplies std::vector
container, that works very well for multi-dimension arrays: in your case, passing vector<vector<int> > &matrix
would be the proper way of dealing with the task in C++.
int calculateDeterminantOfTheMatrix(vector<vector<int> > &matrix) {
int res = 0;
for (int i = 0 ; i != matrix.size() ; i++)
for(int j = 0 ; j != matrix[i].size() ; j++)
res += matrix[i][j];
return res;
}
As an added bonus, you wouldn't need to pass dimensions of the matrix to the function: matrix.size()
represents the first dimension, and matrix[0].size()
represents the second dimension.
why specify column size when pass 2d array into function
While passing an array as an argument to a function, compiler implicitly converts the array reference to the pointer. This can be clearly seen in the case of one dimensional array, like
int method(int *a)
int method(int a[])
Both these lines are equivalent here (although pointer and array reference are different) because whenever an array appears in an expression, the compiler implicitly generates a pointer to the array's first element, just as if the programmer had written &a[0]. However this rule is not recursive i.e. passing a 2d array is treated as pointer to an array, not a pointer to a pointer.
int method(int b[3][5]);
is converted to
int method(int (*b)[5]);
And since the called function doesn't allocate space for the array so size of row is not important, however size of column is still important to provide the size of array. For further reference you can visit here.
How to pass a method the height and width of a 2d array as parameters?
This is a possible solution :
void blackandwhite(int* array, int height, int width)
{
// Array-processing done here.
// array is pointer to int,
// initially points to element myarray[0][0].
// variable height = 2;
// variable width = 4;
}
int main()
{
int myarray[2][4];
blackandwhite(&myarray[0][0], 2, 4);
}
One can find the size of an array i.e. the number of elements in it by the following construct :
int array[8];
int size = sizeof(array)/sizeof(array[0]);
Unfortunately, C arrays are native arrays and do NOT contain any metadata embedded in them. Rows and Columns are just a way of representing/accessing what is essentially linear storage space in memory. AFAIK, there is no way to automatically determine the number of rows/columns of a 2D-array, given a pointer to it (in C).
Hence one needs to pass the number of columns/rows as separate arguments along-with the pointer to the 2D-array as shown in the example above.
More info on a related question here.
UPDATE:
Common pitfall no.1 : Using int** array
in param-list
Note that a pointer to a 2 dimensional array of integers is still a pointer to a int.int**
implies that the param refers to a pointer to a pointer to an int, which is NOT the case here.
Common pitfall no.2 : Using int[][]
in param-list
Failing to pass the dimension(s) of the array. One need NOT pass the size of the array's 1st dimension (but you may but the compiler will ignore it). The trailing dimensions are compulsory though. So,
// is INVALID!
void blackandwhite(int array[][], int height, int width)
// is VALID, 2 is ignored.
void blackandwhite(int array[2][4], int height, int width)
// is VALID.
void blackandwhite(int array[][4], int height, int width)
Related Topics
Throw and Ternary Operator in C++
How to Use 'Const_Cast' to Modify a Constant Variable
C++ Shared Library with Templates: Undefined Symbols Error
How to Guarantee Fast Shutdown of My Win32 App
Symbol Not Found When Using Template Defined in a Library
Programmatically Check Whether My MAChine Has Internet Access or Not
Strange Behavior with Constexpr Static Member Variable
C++ When Should We Prefer to Use a Two Chained Static_Cast Over Reinterpret_Cast
Forcing String to Int Function to Consume Entire String
Displacement Map Filter in Opencv
G++ Linker: Force Static Linking If Static Library Exists
Error Lnk2019 Unresolved External Symbol
Macros in the Middle of a Class or Function Declaration
C++ Get Handle of Open Sockets of a Program
Boost::Asio Synchronous Client with Timeout
Why Does (1 << 31) >> 31 Result in -1