Memory allocation for a 2D array in c++ - c++

I'm new to c++ and trying to understand how memory allocating is done for 2D arrays.I have gone through several threads in SOF and these answers.
answer1
answer2
Those answers says that continuous memory allocation happen for 2D arrays as well like for normal arrays. (correct me if I'm wrong) Answer 2 mention that it should be able to access array[i][j] th element using*(array + (i * ROW_SIZE) + j)
But when I'm trying to do that it gives me an unexpected result.
Code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int array[2][2] = { {1, 2}, {3, 4} };
cout<<*((array+1*2) + 1)<<endl;
cout<<**((array+1*2) + 1)<<endl;
return 0;
}
Result:
0x76e1f4799008
2012576581
It doesn't give me array[i][j] th element. Can some one explain what is happening here, whether that solution is wrong or have i misunderstood the previous answers.

First you have to get a pointer to the first element of the whole thing, i.e. not just to the first row:
int *p = &array[0][0]
After that, you can index p like you want:
std::cout << *(p + 1*2 + 1) << std::endl;
The reason why your initial tries didn't work is related to types. What is happening is that in your first try you are trying to evaluate
*(array + 1*2 + 1)
Now since, array is of type "array-of-length-2" containing "array-of-length-2" containing ints, i.e. (int[2])[2] what this will do is increment array with 3 times the size of its elements, which in turn are int[2]. This will jump outside of your array. In fact *(array+3) is equivalent to array[3]. Now, that clearly is something with type int[2], which will decay to a pointer when you try to print it. In your second try, you dereference this, yielding something like array[3][0], which now is of the right type, but again, points outside of the array.

it is more like when you simulate a 2d array as a one dimensional array like this
0 1 2
3 4 5
6 7 8
and the array will be 0 1 2 3 4 5 6 7 8 to access 4 it should be *(a[0]+(1*3)+1)a[0] is the same as a(name of array).

array is 2D pointer
**array = array[0][0]
*(*array + j) = array[0][j]
*(*(array+i) + j) = array[i][j]

Related

Segmentation fault while taking input in a 2d array in C++

The computer is giving segmentation fault whenever I try to read input into this. My input looks like:
7
1 2 3
2 3 1
1 4 4
4 6 7
7 5 2
3 5 1
4 5 5
Basically, I want to store the above input directly into a 2D array. The first column is X-coordinates, 2nd column Y-coordinate and finally the value needed to store in (X,Y) COORDINATE of a 2D array.
long leastTimeToInterview(int n, int k, int m) {
int a[m+1][m+1];
int i=0,x=0,y=0;
for (i=1;i<=m;i++){
scanf("%d %d",&x,&y);
scanf("%d",&a[x][y]);
a[y][x]=a[x][y];
}
return 11;
}
Like rustyx mentioned, this error could be a result of a stack overflow.
The easiest aproach would be to reduce the size of your array or use another data structure which allocates memory dynamically like std::vector, std::list or std::map.
In your example it also looks as if most of your array is empty. In this case i sugest using std::map.
Some other optimisations in regard of memory usage are discussed in this question: Any optimization for random access on a very big array when the value in 95% of cases is either 0 or 1?
There is no such thing as dynamically sized array in C++'s type system so you need to change it to somthing else like std::vector. The other problem is that even if your compiler supports dynamically sized arrays you still get stack overflow (at least it's very likely). So I suggest that you change your function to something like this:
long leastTimeToInterview(int n, int k, int m) {
std::vector<std::vector<int>> a(m + 1, std::vector<int>(m + 1));
int i = 0, x = 0, y = 0;
for(i = 1; i <= m; i++) {
scanf("%d %d", &x, &y);
scanf("%d", &a[x][y]);
a[y][x] = a[x][y];
}
return 11;
}
There still might be an error in the logic of your application but your example and explanation don't give enough information to tell that.

How does C++ find the size of an array?

Difference From Other Questions
I am not asking how to find the size, but how the computer finds the size.
Goal
I want to find out how C++ finds the size of an array (using sizeof(array)), and a 2D array (using sizeof(array)).
When I ran the code, I thought the output would be 3 and 6. But it was 12 and 24!? How do I make the the output 3 and 6?
I don't know how to calculate the size of an array, so when I say "an output of three/six", I mean the amount of numbers in the array.
Code
#include <iostream>
using namespace std;
int main()
{
int oneDArray [3] = {1, 2, 3};
int twoDArray [2][3] = {{1, 2, 3}, {1, 2, 3}};
cout << sizeof(oneDArray) << "\n" << sizeof(twoDArray);
return 0;
}
The sizeof operator returns the size in bytes, not elements.
For single dimensional arrays (not passed as a function argument, which would cause decay to a pointer), you can get the element count by dividing the size of the array by the size of the first element, e.g.
sizeof(oneDArray) / sizeof(oneDArray[0]) // Gets 3
For multidimensional arrays, that would tell you the size of the first dimension, not the number of elements total, so you'd need to drill down deeper:
sizeof(twoDArray) / sizeof(twoDArray[0]) // Gets 2 (first dimension of array)
sizeof(twoDArray) / sizeof(twoDArray[0][0]) // Gets 6 (number of elements)
You can of course explicitly name the type of an element to avoid nested indexing (sizeof(twoDArray) / sizeof(int) get 6 just fine), but I avoid it as a rule; it's too common for an array to change types during development (say, it turns out you need to use int64_t because you have values into the trillions), and if the whole expression isn't in terms of the array, it's easy to overlook it and end up with broken code.
sizeof returns bytes, if you expect number of elements, divide by the size of each element
cout << sizeof(oneDArray)/sizeof(int) << "\n" << sizeof(twoDArray)/sizeof(int);
Output:
3
6

C++ negative array index [duplicate]

This question already has answers here:
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 5 years ago.
I alloced an int array of 3 elements, and thought of this code below:
int a[3];
for(int i = -2; i < 3; ++i){
a[i] = i;
cout<<a[i]<<" ";
}
Here's its output:
-2 -1 0 1 2
It seems like array a has 5 alloced space, and a is at the middle of those space.
Any ideas?
To explain how negative indexes work, you first have to learn (or remember) that for any array or pointer a and index i, the expression a[i] is equal to *(a + i).
That means that you can have a pointer to the middle element of an array, and use it with a positive or negative index, and it's simple arithmetic.
Example:
int a[3] = { 1, 2, 3 };
int* p = &a[1]; // Make p point to the second element
std::cout << p[-1]; // Prints the first element of a, equal to *(p - 1)
std::cout << p[ 0]; // Prints the second element of a, equal to *p
std::cout << p[ 1]; // Prints the third element of a, equal to *(p + 1)
Somewhat graphically it can be seen like
+------+------+------+
| a[0] | a[1] | a[2] |
+------+------+------+
^ ^ ^
| | |
p-1 p p+1
Now when using a negative index in an array, as in the example of a in the question, it will be something like this:
+-----+-------+-------+------+------+------+
| ... | a[-2] | a[-1] | a[0] | a[1] | a[2] |
+-----+-------+-------+------+------+------+
That is, negative indexes here will be out of bounds of the array, and will lead to undefined behavior.
That is something you should never ever do! C++ doesn't check the boundaries of built in plain arrays so technically you can access locations which are out of the allocated space (which is only 3 ints not 5) but you will ultimately produce errors.
When I ran this on my own IDE (Visual Studio 2017) it threw an exception stating that the stack around the array had become corrupted. What I think is happening is that 3 spaces in memory are being allocated but you force the array to write to five spaces, those preceding and after the initial allocation. This will work technically, but is definitely not recommended. You are basically writing over top of something in your memory and that can have bad consequences when done in large arrays.

C++ Arrays and overflow

I am mis-understanding something about the code below. From my understanding the tester declaration should return a pointer to the first array of two elements, i.e. [1,2], and so *(tester+1) should return [3,4], which only has 2 elements so how does it make sense to call (*(tester + 1))[2] . This example prints the number 5 by the way. Any clarifications much appreciated.
int main() {
int tester[][2]{ 1,2,3,4,5,6 };
cout << (*(tester + 1))[2] << endl;
return 0;
}
When you declare a 2-dimensional array, all the elements are contiguous. The entire array is a single object, so you're not going out of bounds when you just exceed one of the row limits, so longer as you're still in the array. So the next element after tester[1,1] is tester[2,0], and that's what (*(tester + 1))[2] accesses.
[2] is higher than the highest element at [1] because the index starts at [0]
There are three arrays.
[1,2] positions 0,0 and 0,1
[3,4] positions 1,0 and 1,2
[5,6] positions 2,0 and 2,1
Since all of the arrays are next to each other in the data segment, going out of bounds on the second array (tester + 1) bleeds over into the third array giving you the first element of the third array.
i.e. position 1,2 is the same as 2,0
int tester[][2]{ 1,2,3,4,5,6 } creates a 3 by 2 array.
tester[0][0] = 1
tester[0][1] = 2
tester[1][0] = 3
tester[1][1] = 4
tester[2][0] = 5
tester[2][1] = 6
The compiler creates an array using the least amount of memory possible based on your specifications. [][2] explicit says to organize the data in such a fashion that there a x rows and 2 columns. Because you put 6 elements into the tester array, the compiler decides the number of rows to assign by dividing the number of total elements by the number of columns.
Furthermore, (*(tester + 1))[2], is equivalent to tester[2], which would access the element in the first column of the third row. Thus returning 5.
It is another way to write this code which means you define vector but it acts like 2-dimensional array.
int main() {
int tester[3][2]{ {1,2},{3,4},{5,6} };
std::cout<< tester[1][2] <<std::endl;
return 0;
}

Pointers of arrays

#include<iostream>
#include<iomanip>
void main()
{
int i,j;
int pole[3][3]={1,2,3,4,5,6,7,8,9};
*(*(pole+2)+2)=0;
for(i=0; i<3;i++)
{
for(j=0;j<3;j++)
{
cout << setw(5)<< pole[i][j];
}
cout << endl;
}
}
This is my program and the output I get is the following:
1 2 3
4 5 6
7 8 0
However, I have troubles understanding what exactly does this line mean:
*(*(pole+2)+2)=0;
In my understanding, it's a pointer to pointer of array, so basically, the first we do:
*(pole+2)
which points to the 2nd element of the array. Then
*(*(pole+2)+2)
which points to the 4th element of the array? Is this correct? If so, how do we change the last [3][3] element to 0?
Thank you.
Here pole is a 2D array of 3 rows and 3 columns. So as array index starts from 0, you are assigning pole[2][2] = 0 which actually means 0 is assigned to 3rd row and 3rd column element.
*(*(pole+2)+2) == *(pole[2] + 2) == pole[2][2]
I just learned about pointers in and arrays in depth in my C++ so i hope i can help
you declared a 2D Array which is really just an array of an array of int types.
(pole + 2) points to pole's base address and adds 2(size of an array of ints) to it so:
2*int(4 bytes) * 3(size of array) = 24 bytes
so it adds 24 bytes to the address. it is now pointing to the 3rd array. then it takes that and points to:
3rd arrays base address + 2*int(4bytes)
which will lead it to the 3rd index of that array which is 9. It then changes this value to 0.
the key is that the first pointer is pointing to an Array of arrays. the second pointer points to the index inside of that array.
I hope i didn't confuse you.