Can I access elements of a 2D array using pointers in C++? - c++

For 1D array, I can use array name as a pointer and add offset to it to access each element of the array. Is there something similar for 2D arrays?
I defined a 2D array as follows
int arr[2][3] = {{1,2,3}, {4,5,6}};
int** arrPtr = arr;
but I got compiler error for the second line. Shouldn't 2D array have type int**?
I came across another thread here:
C++ Accessing Values at pointer of 2D Array
and saw this:
2dArray = new int*[size];
Could someone please tell me what int*[size] means? (size is an int, I presume).
Thanks a lot.

A multidimensional array defined as yours is is only a single pointer, because the data is encoded in sequence. Therefore, you can do the following:
int arr[2][3]={{1,2,3},{4,5,6}};
int* arrPtr = (int*)arr;
In general, the pointer to the element at arr[a][b] can be accessed by arrPtr + a*bSize + b where bSize is the size of the first array dimension (in this case three).
Your second question relates to dynamic memory allocation - allocating memory at runtime, instead of defining a fixed amount when the program starts. I recommend reviewing dynamic memory allocation on cplusplus.com before working with dynamically allocated 2D arrays.

int* array[10] means an array of 10 pointers to integer.
You can access a 2D array with a simple pointer to its first entry and do some maths exploiting the spacial location principle.
int array[2][2] = {{1,2}, {3, 4}};
int* p = &array[0][0];
for(int i=0; i<2*2; i++)
printf("%d ", *(p++));
If you have a matrix:
1 2
3 4
in memory it is encoded as 1 2 3 4 sequentially ;)

Related

Declaring a 2D array using double pointer

I am confused about this line in a C++ program. The idea of the program is to check whether a 4x4 array is symmetric or not. This part of the code declares a 2D array, which I do not understand.
int** array = new int*[n];
Although, there is another question similar to this but it is about single pointer which I get.
int *array = new int[n];
I do not understand the double pointer. Kindly explain.
How do you create a single pointer array? You do this:
int* myArray = new int[n];
What does this mean? It has two parts. First part is reserving a pointer int* we call it myArray, and the second part is that you reserve n elements, each with size int in memory (this is an array, right?), and you take the address of that array and you save it in the variable myArray.
Now you want a 2D array, which is an array of an array. So Every element of this new array of array is one of these, that we talked about up there. How do we reserve this? We do:
new int*[n];
Because we are reserving n slots, each with type int*, that we talked about before.
Now what is the type of the return value? It's an array of an array, or a "pointer to an array, and the latter is also a pointer to an array", so you write it as
(int*)*
Or
int**
so it becomes
int** array = new int*[n];
int** array is a pointer to a pointer to an int. So by doing this:
int** array = new int*[n];
you are creating a section of memory that holds n int* pointers and pointing array at that memory. For each of these pointers that you have created, it is possible to create a set of ints like so:
for (auto i = 0; i < n; ++i)
array[i] = new int[n];
The resulting memory will look like this:
array -> [ int* | int * | .... n
[int | int | ...][int | int | ...][ ... n
This is however, much much easier if you use some of the std things in c++, ie a std::vector :
std::vector<std::vector<int>> arr(std::vector<int>(0, n), n);
and you are done ...

C++ Syntax - Multidimensional Dynamic Array

I need help understanding the syntax of multidimensional arrays in C++. In the book I'm learning C++ from, the code snippet looks like this:
typedef int* IntArrayPtr;
IntArrayPtr *m = new IntArrayPtr[num_rows];
for(int i = 0; i < rows; i++){
m[i] = new int[num_columns]
}
My question is this: Why is there a star infront of the m? To me when I see
new IntArrayPtr[num_rows];
that's enough information to tell the compiler that it's an array of pointers that point to int. The star just makes it confusing. Is there something I'm missing here?
Keep in mind that what you have when you do new IntArrayPtr[num_rows] is an array of IntArrayPtrs. In C new[], "allocates size bytes of storage, suitably aligned to represent any object of that size, and returns a non-null pointer to the first byte of this block." So new[] is returning you a pointer to the first element of your array.
For example if num_rows is 3 this is what gets allocated in memory:
m --> [IntArrayPtr]
[IntArrayPtr]
[IntArrayPtr]
m being a pointer is what allows you to use the index operator on it: m[1] returns you the second IntArrayPtr in m.
m is the pointer to pointer which handles starting points of columns as a row. Example of this example in c
int **arr=(int**)malloc(num_rows * (sizeof(int*) ) );
for(i=0;i<row;i++)
{
arr[i]=(int*)malloc(sizeof(int)*col_rows);
}
if we use typedef,
typedef int* IntArrayPtr;
IntArrayPtr *arr=(IntArrayPtr*)malloc(num_rows * (sizeof(IntArrayPtr) ) );
for(i=0;i<row;i++)
{
arr[i]=(IntArrayPtr)malloc(sizeof(int)*col_rows);
}
As you see, firstly we create a pointer array to hold pointers of columns. After that we allocate a place for every columns of array and assign starting points of one dimensional column arrays to one dimensional pointer array.

How to create a pointer to pointers

The problem that I have is to create a specific matrix.
I have to use an array called for example ptr with x pointers. Each pointer in this array should point to a new array (in this case, an int array; each array is a new line in the matrix then).
All x arrays should be created with new; in the end, it should be possible to access the matrix with ptr[a][b] easily.
After a lot of trying and failing, I hope that someone can help me out.
Thank you in advance!
Since this is obviously homework, let me give you a better answer for your sake to go alongside the accepted one.
std::vector<std::vector<int>> matrix(10, std::vector<int>(10));
// ^ ^ ^
// Column count ______| |________________|
// |
// |___ Each column is
// initialized with
// a vector of size 10.
That's a 10x10 matrix. Since we're using vectors, the sizes are dynamic. For statically sized arrays, you can use std::array if you want. Also, here's the reference for std::vector.
If the number of pointers in the array is known, you could simply use a raw array of pointers to int:
int* my_array[10]; // 10 int*
Then you should allocate memory individually for each pointer in the array using usually a for loop:
for(int i=0; i<10; i++){
// each int* in the array will point to an area equivalent to 10 * sizeof(int)
my_array[i] = new int[10];
}
On the other hand, if you don't know the size of the array, then you need a pointer to pointers:
int** ptr_to_ptr = new int*[10];
Note that I am allocating space for 10 int* and not int.
Remember to deallocate the memory allocated above also for the internal pointers, once you don't need that memory anymore.

Dynamic Memory allocation in 2-D Array

I have to create dynamic 2d array.I was trying with the code mentioned below:
Suppose a=512 and b =102.So Now the 2-D Array created is ary[512][102].
Now I am Creating a pointer to base location i.e int *ptr=&(ary[0][0]);
Now, if I am giving pointer the offset 102 i.e ptr+=102, it should point to &(ary[1][0]) but it doesn't point to.
If given offset of 104 then only it points to &(ary[1][0]). Why it requires extra 2 Offset????
Code Snippet:
int** ary;
ary= new int*[a];
for(int i = 0; i < a; ++i)
ary[i] = new int[b];
your 2d array is dynamically allocated as your code suggested, so the address of this 2d arrays is not in sequence, thus &(ary[0][0])+102, you can't grantee the pointer returned is the next row. So in this case, you should just use &(ary[1][0])
Unlike in the static allocation of 2D arrays, the addresses are not consecutive for the whole array when you use multiple new. Instead when you call for new() to create rows of a 2D array each new returns completely unrelated addresses which are allocated from heap. So you have to use ary[n] to access elements of (n + 1)th row and ary[n+1] to access elements of (n+2)th row and so on.
In this case, your 2-D array is not necessarily linear in the actual memory. So you can not write a program assumming that the memory is linear.
The reason for 104 pointing to ary[1][0] could be the boundary alignment. The run time system chooses to use 104 bytes for your ary[i], rather than 102.

Multi-dimensional array and pointers in C++?

int *x = new int[5]();
With the above mentality, how should the code be written for a 2-dimensional array - int[][]?
int **x = new int[5][5] () //cannot convert from 'int (*)[5]' to 'int **'
In the first statement I can use:
x[0]= 1;
But the second is more complex and I could not figure it out.
Should I use something like:
x[0][1] = 1;
Or, calculate the real position then get the value
for the fourth row and column 1
x[4*5+1] = 1;
I prefer doing it this way:
int *i = new int[5*5];
and then I just index the array by 5 * row + col.
You can do the initializations separately:
int **x = new int*[5];
for(unsigned int i = 0; i < 5; i++)
x[i] = new int[5];
There is no new[][] operator in C++. You will first have to allocate an array of pointers to int:
int **x = new int*[5];
Then iterate over that array. For each element, allocate an array of ints:
for (std::size_t i = 0; i < 5; ++i)
x[i] = new int[5];
Of course, this means you will have to do the inverse when deallocating: delete[] each element, then delete[] the larger array as a whole.
This is how you do it:
int (*x)[5] = new int[7][5] ;
I made the two dimensions different so that you can see which one you have to use on the lhs.
Ff the array has predefined size you can write simply:
int x[5][5];
It compiles
If not why not to use a vector?
There are several ways to accomplish this:
Using gcc's support for flat multidimensional arrays (TonyK's answer, the most relevant to the question IMO). Note that you must preserve the bounds in the array's type everywhere you use it (e.g. all the array sizes, except possibly the first one), and that includes functions that you call, because the produced code will assume a single array. The allocation of $ new int [7][5] $ causes a single array to be allocated in memory. indexed by the compiler (you can easily write a little program and print the addresses of the slots to convince yourself).
Using arrays of pointers to arrays. The problem with that approach is having to allocate all the inner arrays manually (in loops).
Some people will suggest using std::vector's of std::vectors, but this is inefficient, due to the memory allocation and copying that has to occur when the vectors resize.
Boost has a more efficient version of vectors of vectors in its multi_array lib.
In any case, this question is better answered here:
How do I use arrays in C++?