Pointers of arrays - c++

#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.

Related

Memory allocation for a 2D array in 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]

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;
}

Strange behavior of C++ array size

I am writing a c++ function to calculate the size of an C-type array in C++
I noticed a very strange behavior when using these two different codes:
code 1:
int sz = sizeof array / sizeof *array;
code 2:
int array_size(const int *pointer)
{ int count=0;
if(pointer)
while(*pointer) {
count++;
pointer++;
}
return count;
}
When I applied these two method on a array, it gave me very strange behavior:
example 1 :
int array[10] = {31,24,65,32,14,5};// defined to be size 10 but init with size 6
the code one will give me size = 10, but code 2 will give me size 6,and when I print out the element that is pointed by *pointer, it will give me the correct array elements:
31 24 65 32 14 5
example 2
int array[] = {31,24,65,32,14,5}; // no declared size but init with 6
Code 1 will give me size 6, code 2 will give me size 12, and when I print out the element that is pointed by *pointer in code 2, it gives me :
31 24 65 32 14 5 -802013403 -150942493 1461458784 32767 -1918962231 32767
which is really not right, so what could be the problem that cause this behavior? and what are those numbers?
Thanks for your answer
This array has 10 elements, regardless of how you initialize it:
int array[10] = {31,24,65,32,14,5};
But the initialization sets the first 6 elements to certain values, and the rest to 0. It is equivalent to this:
int array[10] = {31,24,65,32,14,5,0,0,0,0};
The first calculation using sizeof uses the actual size fo the array (its length times the size of an int), while the second one counts elements until it finds a 0. So it doesn't calculate the length of the array, but the length of the first non-zero sequence in the array.
Note that the second method only "works" if the array has an element with value 0. Otherwise you go out of bounds and invoke undefined behaviour.
array_size assumes that there is a 0 just past the end of the array. That assumption is unjustified.
code 2 is not right. you can't assume an array end with 0

I don't understand how to create and use dynamic arrays in C++

Okay so I have;
int grid_x = 5
int * grid;
grid = new int[grid_x];
*grid = 34;
cout << grid[0];
Should line 3 create an array with 5 elements? Or fill the first element with the number 5?
Line 4 fills the first element, how do I fill the rest?
Without line 4, line 5 reads "-842150451".
I don't understand what is going on, I'm trying to create a 2 dimensional array using x and y values specified by the user, and then fill each element one by one with numeric values also specified by the user. My above code was an attempt to try it out with a 1 dimensional array first.
The default C++ way of creating a dynamic(ally resizable) array of int is:
std::vector<int> grid;
Don't play around with unsafe pointers and manual dynamic allocation when the standard library already encapsulates this for you.
To create a vector of 5 elements, do this:
std::vector<int> grid(5);
You can then access its individual elements using []:
grid[0] = 34;
grid[1] = 42;
You can add new elements to the back:
// grid.size() is 5
grid.push_back(-42);
// grid.size() now returns 6
Consult reference docs to see all operations available on std::vector.
Should line 3 create an array with 5 elements?
Yes. It won't initialise them though, which is why you see a weird value.
Or fill the first element with the number 5?
new int(grid_x), with round brackets, would create a single object, not an array, and specify the initial value.
There's no way to allocate an array with new and initialise them with a (non-zero) value. You'll have to assign the values after allocation.
Line 4 fills the first element, how do I fill the rest?
You can use the subscript operator [] to access elements:
grid[0] = 34; // Equivalent to: *(grid) = 34
grid[1] = 42; // Equivalent to: *(grid+1) = 42
// ...
grid[4] = 77; // That's the last one: 5 elements from 0 to 4.
However, you usually don't want to juggle raw pointers like this; the burden of having to delete[] the array when you've finished with it can be difficult to fulfill. Instead, use the standard library. Here's one way to make a two-dimensional grid:
#include <vector>
std::vector<std::vector<int>> grid(grid_x, std::vector<int>(grid_y));
grid[x][y] = 42; // for any x is between 0 and grid_x-1, y between 0 and grid_y-1
Or might be more efficient to use a single contiguous array; you'll need your own little functions to access that as a two-dimenionsal grid. Something like this might be a good starting point:
template <typename T>
class Grid {
public:
Grid(size_t x, size_t y) : size_x(x), size_y(y), v(x*y) {}
T & operator()(size_t x, size_t y) {return v[y*size_x + x];}
T const & operator()(size_t x, size_t y) const {return v[y*size_x + x];}
private:
size_t size_x, size_y;
std::vector<T> v;
};
Grid grid(grid_x,grid_y);
grid(x,y) = 42;
Should line 3 create an array with 5 elements? Or fill the first element with the number 5?
Create an array with 5 elements.
Line 4 fills the first element, how do I fill the rest?
grid[n] = x;
Where n is the index of the element you want to set and x is the value.
Line 3 allocates memory for 5 integers side by side in memory so that they can be accessed and modified by...
The bracket operator, x[y] is exactly equivalent to *(x+y), so you could change Line 4 to grid[0] = 34; to make it more readable (this is why grid[2] will do the same thing as 2[grid]!)
An array is simply a contiguous block of memory. Therefore it has a starting address.
int * grid;
Is the C representation of the address of an integer, you can read the * as 'pointer'. Since your array is an array of integers, the address of the first element in the array is effectively the same as the address of the array. Hence line 3
grid = new int[grid_x];
allocates enough memory (on the heap) to hold the array and places its address in the grid variable. At this point the content of that memory is whatever it was when the physical silicon was last used. Reading from uninitialised memory will result in unpredictable values, hence your observation that leaving out line 4 results in strange output.
Remember that * pointer? On line four you can read it as 'the content of the pointer' and therefore
*grid = 34;
means set the content of the memory pointed to by grid to the value 34. But line 3 gave grid the address of the first element of the array. So line 4 sets the first element of the array to be 34.
In C, arrays use a zero-based index, which means that the first element of the array is number 0 and the last is number-of-elements-in-the-array - 1. So one way of filling the array is to index each element in turn to set a value to it.
for(int index = 0; index < grid_x; index++)
{
grid[index] = 34;
}
Alternatively, you could continue to use a pointer to do the same job.
for(int* pointerToElement = grid; 0 < grid_x; grid_x-- )
{
// save 34 to the address held by the pointer
/// and post-increment the pointer to the next element.
*pointerToElement++ = 34;
}
Have fun with arrays and pointers, they consistently provide a huge range of opportunities to spend sleepless hours wondering why your code doesn't work, PC reboots, router catches fire, etc, etc.
int grid_x = 5
int * grid;
grid = new int[grid_x];
*grid = 34;
cout << grid[0];
Should line 3 create an array with 5 elements? Or fill the first
element with the number 5?
Definitely the former. With the operator "new" you are allocating memory
Line 4 fills the first element, how do I fill the rest?
Use operator [], e.g.:
for int (i=0; i < grid_x; i++) { //Reset the buffer
grid[i] = 0;
}
Without line 4, line 5 reads "-842150451".
You are just reading uninitialized memory, it could be any value.
I don't understand what is going on, I'm trying to create a 2
dimensional array using x and y values specified by the user, and then
fill each element one by one with numeric values also specified by the
user. My above code was an attempt to try it out with a 1 dimensional
array first.
Other users explained how to use vectors. If you have to set only once the size of your array, I usually prefer boost::scoped_array which takes care of deleting when the variable goes out of scope.
For a two dimensional array of size not known at compile time, you need something a little bit trickier, like a scoped_array of scoped_arrays. Creating it will require necessarily a for loop, though.
using boost::scoped_array;
int grid_x;
int grid_y;
///Reading values from user...
scoped_array<scoped_array<int> > grid(new scoped_array<int> [grid_x]);
for (int i = 0; i < grid_x; i++)
grid[i] = scoped_array<int>(new int[grid_y] );
You will be able then to access your grid elements as
grid[x][y];
Note:
It would work also taking scoped_array out of the game,
typedef int* p_int_t;
p_int_t* grid = new p_int_t [grid_x];
for (int i = 0; i < grid_x; i++)
grid[i] = new int[grid_y];
but then you would have to take care of deletion at the end of the array's life, of ALL sub arrays.

Why am i getting this kind of output since i know that the default values of non-initialized integer elements of an array is 0?

#include <iostream>
using namespace std;
void RemoveZeroElements(int arr1[],int arr2[],int &i){
int n=0;
int m=0;
while(n<14) {
switch(arr1[n]) {
case 0:
n+=1;
break;
default:
arr2[m]=arr1[n];
m+=1;
n+=1;
i+=1;
break;
}
}
}
int main()
{
int ar1[14]={2,4,5,0,7,-9,0,0,11,23,44,0,13,999};
int ar2[14];
int efsize=0;
RemoveZeroElements(ar1,ar2,efsize);
cout<<"the new array without the zeros has an effective size of "<< efsize << endl;
for (int i=0;i<14;i++) {
if(ar2[i]!=0) {
cout << "the new array has its " << (i+1)<< "th element set to " <<
ar2[i]<< endl;
}
}
}
The output i get is the following:
the new array without the zeros has an effective size of 10
the new array has its 1th element set to 2
the new array has its 2th element set to 4
the new array has its 3th element set to 5
the new array has its 4th element set to 7
the new array has its 5th element set to -9
the new array has its 6th element set to 11
the new array has its 7th element set to 23
the new array has its 8th element set to 44
the new array has its 9th element set to 13
the new array has its 10th element set to 999
the new array has its 11th element set to 1
the new array has its 12th element set to 65535
the new array has its 13th element set to 4308980
the new array has its 14th element set to -1079890440
The problem as you see is in the 12th,13th and 14th elements
What you know is wrong. The initial values of array elements of POD type (such as int or void * or struct some_standard_c_structure) with function scope is undefined. ar2 is full of garbage.
The initial values of array elements with static or global scope is 0 (not taking into account multithreading issues.)
You must make sure to clear the contents of ar2 before you use it. The simplest way to do so is with std::fill():
std::fill(ar2, ar2 + (sizeof(ar2) / sizeof(int)), 0);
In C, the equivalent is memset():
memset(ar2, 0, sizeof(ar2));
Because you are wrong. Those are uninitialized values, could be anything.
If they were static storage duration objects, instead of auto storage duration objects, they would be initialized to zero. It's best not to think about it and always initialize your variables.
What you're doing here is setting the first ten elements of ar2 to the numbers in ar1 that aren't zero. Your problem elements aren't just the 12th, 13th, and 14th, it also includes the 11th as well. You'll notice that the number 1 is nowhere in your original array also.
The last four elements aren't zero, they're completely undeclared, because of what he said ^^ up there. If you want the ar2 to be ar1 without the zeros, just do a count in a for loop that counts how many elements are NOT zero, and initialize ar2 to that number.