What does exactly name of 2D array represents? - c++

Like name of 1D array represents address of a[0], what does name of 2D array represents?
If it also represents address of a[0][0], then why
I get error using this :
int a[2][2];
sort(a,a+4);
While,
sort(&a[0][0] , &a[0][0]+4)
works perfectly fine.

In case of 1D array like
int arr[5] = {1,2,3,4,5};
arr means array name and it represents base address of arr. And arr and address of arr[0] is same.
Similarly in case of 2D array like
int arr[2][2] = { {1,2},{3,4}};
arr means array name and it represents base address of arr.
printf("%p\n",(void*)arr);
printf("%p\n",(void*)&arr[0]);
printf("%p\n",(void*)&arr[0][0]);
Above all printf() results in same output.
Note : In below case
int a[2][2];
sort(a,a+4);
a+4 doesn't exists at all, you have only a+0 and a+1.
a[0][0] a[0][1] a[1][0] a[1][1]
|(0x100) |(0x104) |(0x108) |(0x10c)
------------- ------------
| |
a[0](0x100) a[1](0x108) or a+1 ... there is no a+4
| |
----------------------
|
a (0x100<- assume base address of 2D array a is ox100)
While &a[0][0]+4 is different, it is (0x100 + 4 * sizeof(a[0][0]) i.e 0x110(in hexa).

A 2D array is an array of arrays and works in exactly the same way as a 1D array:
int a[10];
a == &a[0];
int* = &a[0];
int b[10][20];
b == &b[0];
int** = &b[0];
The name of a 2D array is equivalent to a pointer to the first element of the outer array which is the inner 1D array.

Related

Arrays and pointers arithmetic confusion

#include <iostream>
using namespace std;
int main ()
{
int numbers[5];
int * p;
p = numbers; *p = 10;
p++; *p = 20;
p = &numbers[2]; *p = 30;
p = numbers + 3; *p = 40;
p = numbers; *(p+4) = 50;
for (int n=0; n<5; n++)
cout << numbers[n] << ", ";
return 0;
}
Fairly new coder here. This is an example taken from the pointers page on cplusplus.com. They talk about dereferencing, the address of operator, and then they talk about the relationship between arrays and pointers. I noticed if I simply printed out a declared array it spits out the address of the array. I'm really trying to understand exactly what some of these lines of code are doing and am having a hard time.
Everything makes sense up until *p=10. I read this as, "the value being pointed to by pointer p is equal to 10" but an array isn't just one value. In this case it's 5... So, whats the deal? Will the compiler just assume we are talking about the first element of the array?
Even more confusing for me is p++;. p right now is the address of the array. How do you do p=p+1 when p is an address?
I understand p= &numbers[2];. As well as the following *p = 30;.
p = numbers + 3; confuses me. Why are we able to take an address and just add 3 to it? And, what does that even mean?
Everything within the for loop makes sense. It's just printing out the array correct?
Thanks for your help in advance!
As Pointed out this due to pointer arithmetic.
So both array numbers and pointer p are int, so after assigning numbers's base address to pointer p and the *p=10 does numbers[0]=10
Now when you do p++ the address of p is incremented but not to the next numeric value as in normal arithmetic operation of ++ but to the address of the next index of numbers.
Let's assume a int is 4byte of memory and numbers's initial address is 1000.
So p++ makes address it to be incremented to 1004 which is numbers[1]
Basically it points to the next int variable position in memory.
So when *p = 20 is encountered the value 20 will be assigned to the next adjacent memory i.e. 1004 or numbers[1]=20.
After that the p directly assigned address of 3rd index numbers[2] i.e 1008 (next int var in memory). Now p is pointing to the 3rd index of numbers so *p=30 is again numbers[2]=30
p = numbers + 3; *p = 40; does similar thing that is assigns base address of numbers incremented by 3 indexes (1000 + 3*sizeof(int) =1012 ==> 1000 + 3*4 =1012) to p and assigns 40 to that. so it becomes equivalent to numbers[3]=40.
Then p = numbers; *(p+4) = 50; is assigning 1000 to p and the adding 4 to the address of p by using the () and assigns 50 to the value by using *() which is value of the address(1000+ 4*4 = 1016) inside the braces.
Using a pointer like this in C++: p = numbers makes p point to the first element of the array. So when you do p++ you are making p point to the second element.
Now, doing *p = 10 assigns 10 to whatever p is pointing to, as in your case p is pointing to the first element of the array, then *p = 10 is the same as numbers[0] = 10.
In case you see this later: *(p + i) = 20, this is pointer arithmetic and is the same as p[i] = 20. That's why p[0] = 10 is equivalent to *(p + 0) = 10 and equivalent to *p = 10.
And about your question: How do you do p=p+1 when p is an address?: as arrays in C++ are stored sequentially in memory, if the element p is pointing at memory address 6400010 then p++ points at 6400014 assuming each element pointed by p occupies 4 bytes. If you wonder why p++ is 6400014 instead of 6400011, the reason is a little magic C++ does: when increasing a pointer, it doesn't increase by 1 byte but by 1 element so if you are pointing to integers, each one occupying 4 bytes, then p will be increased by 4 instead of 1.
Let's break it down:
int numbers[5];
int * p;
Assigning the array variable to a pointer means that the pointer will be pointing to the first element:
p = numbers; // p points to the 1st element
*p = 10; // 1st element will be 10
p++; // go to next location i.e. 2nd element
*p = 20; // 2nd element will be 20
You can do pointer arithmetic and it works according to the type. Incrementing an int pointer on a 32-bit machine will do a jump of 4 bytes in memory. On a 64-bit machine, that will be 8 bytes. Keep in mind that you cannot do this with a void pointer.
p = &numbers[2]; // assign the address of 3rd element
*p = 30; // 3rd element will be 30
p = numbers + 3; // numbers + 3 means the address of 4th element
*p = 40; // 4th element will be 40
p = numbers; // p points to the 1st element
*(p + 4) = 50; // p + 4 means the address of 5th element
// dereference 5th location and assign 50
// 5th element will be 50
There are a lot of pages on the web on how pointers work. But there are a couple things to quickly point out.
int* p;
The above line mean p is a pointer to an int. Assigning something to it doesn't change what it is. It is a pointer to an int, not an array of int.
int number[5];
p = number;
This assignment takes the address where the array is stored, and assigns it to p. p now points to the beginning of that array.
p++;
p now points to the 2nd int in the array. Pointers are incremented by the size of the object they point to. So the actual address may increase by 4 or 8, but it goes to the next address of an int.
*p = 30;
This is an assignment, not a comparison. It doesn't say that what p points to is 30, it copies 30 into the address pointed to by p. Saying "equals" is generally confusing in programming terms, so use either "assign" or "compare" to be clear.
1> p=numbers;
pointer p now points to the start of the array, i.e first element.
2> *p=10;
first element now becomes 10, as p is pointing to the first element.
3> p++;
this moves the pointer to the next element of the array, i.e second element
So, again *p=20; will make second element=20
4> p = &numbers[2];
this statement means that p now points to 3rd element of the array.
So, *p = 30; will make 3rd element=30
5> p = numbers + 3;
Wen we do p=numbers+1; it points to second element, so p=numbers+3; will now point to 4th element of array. *p = 40; make the fourth element=40
6> p = numbers;
Again p points to first element of array
*(p+4) = 50; will now make 5th element=50

How are 2-Dimensional Arrays stored in memory?

#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[101][101];
a[2][0]=10;
cout<<a+2<<endl;
cout<<*(a+2)<<endl;
cout<<*(*(a+2));
return 0;
}
Why are the values of a+2 and *(a+2) same? Thanks in advance!
a is a 2D array, that means an array of arrays. But it decays to a pointer to an array when used in appropriate context. So:
in a+2, a decays to a pointer to int arrays of size 101. When you pass is to an ostream, you get the address of the first element of this array, that is &(a[2][0])
in *(a+2) is by definition a[2]: it is an array of size 101 that starts at a[2][0]. It decays to a pointer to int, and when you pass it to an ostream you get the address of its first element, that is still &(a[2][0])
**(a+2) is by definition a[2][0]. When you pass it to an ostream you get its int value, here 10.
But beware: a + 2 and a[2] are both pointers to the same address (static_cast<void *>(a+2) is the same as static_cast<void *>(a[2])), but they are pointers to different types: first points to int array of size 101, latter to int.
I'll try to explain you how the memory is mapped by the compiler:
Let's consider a more pratical example multi-dimentional array:
int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
You can execute the command
x/10w a
In GDB and look at the memory:
0x7fffffffe750: 1 2 3 4
0x7fffffffe760: 5 6 7 8
0x7fffffffe770: 9 0
Each element is stored in a int type (32 bit / 4 bytes).
So the first element of the matrix has been stored in:
1) a[0][0] -> 0x7fffffffe750
2) a[0][1] -> 0x7fffffffe754
3) a[0][2] -> 0x7fffffffe758
4) a[1][0] -> 0x7fffffffe75c
5) a[1][1] -> 0x7fffffffe760
6) a[1][2] -> 0x7fffffffe764
7) a[2][0] -> 0x7fffffffe768
...
The command:
std::cout << a + 2 << '\n'
It will print the address 0x7fffffffe768 because of the
pointer aritmetic:
Type of a is int** so it's a pointer to pointers.
a+2 is the a[0] (the first row) + 2. The result is a pointer
to the third row.
*(a+2) deferences the third row, that's {7,8,9}
The third row is an array of int, that's a pointer to int.
Then the operator<< will print the value of that pointer.
A 2-dimensional array is an array of arrays, so it's stored like this in memory:
char v[2][3] = {{1,3,5},{5,10,2}};
Content: | 1 | 3 | 5 | 5 | 10 | 2
Address: v v+1 v+2 v+3 v+4 v+5
To access v[x][y], the compiler rewrites it as: *(v + y * M + x) (where M is the second dimension specified)
For example, to access v[1][1], the compiler rewrites it as *(v + 1*3 + 1) => *(v + 4)
Be aware that this is not the same as a pointer to a pointer (char**).
A pointer to a pointer is not an array: it contains and address to a memory cell, which contains another address.
To access a member of a 2-dimensional array using a pointer to a pointer, this is what is done:
char **p;
/* Initialize it */
char c = p[3][5];
Go to the address specified by the content of p;
Add the offset to that address (3 in our case);
Go to that address and get its content (our new address).
Add the second offset to that new address (5 in our case).
Get the content of that address.
While to access the member via a traditional 2-dimensional array, these are the steps:
char p[10][10];
char c = p[3][5];
Get the address of pand sum the first offset (3), multiplied by the dimension of a row (10).
Add the the second offset (5) to the result.
Get the content of that address.
If you have an array like this
T a[N];
then the name of the array is implicitly converted to pointer to its first element with rare exceptions (as for example using an array name in the sizeof operator).
So for example in expression ( a + 2 ) a is converted type T * with value &a[0].
Relative to your example wuth array
int a[101][101];
in expression
a + 2
a is converted to rvalue of type int ( * )[101] and points to the first "row" of the array. a + 2 points to the third "row" of the array. The type of the row is int[101]
Expression *(a+2) gives this third row that has type int[101] that is an array. And this array as it is used in an expression in turn is converted to pointer to its first element of type int *.
It is the same starting address of the memory area occupied by the third row.
Only expression ( a + 2 ) has type int ( * )[101] while expression *( a + 2 ) has type int *. But the both yield the same value - starting address of the memory area occupied by the third row of the array a.
The first element of an array is at the same location as the array itself - there is no "empty space" in an array.
In cout << a + 2, a is implicitly converted into a pointer to its first element, &a[0], and a + 2 is the location of a's third element, &a[2].
In cout << *(a + 2), the array *(a + 2) - that is, a[2] - is converted into a pointer to its first element, &a[2][0].
Since the location of the third element of a and the location of the first element of the third element of a are the same, the output is the same.

How do sizeof(arr) / sizeof(arr[0]) work?

When looking for a size of an array in a for loop I've seen people write
int arr[10];
for(int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){}
How is sizeof(arr) / sizeof(arr[0]) the length of the array? How does it technically work?
If you have an array then sizeof(array) returns the number of bytes the array occupies. Since each element can take more than 1 byte of space, you have to divide the result with the size of one element (sizeof(array[0])). This gives you number of elements in the array.
Example:
std::uint32_t array[10];
auto sizeOfInt = sizeof(std::uint32_t); // 4
auto numOfBytes = sizeof(array); // 10*sizeOfInt = 40
auto sizeOfElement = sizeof(array[0]); // sizeOfInt = 4
auto numOfElements = sizeof(array) / sizeof(array[0]); // numOfBytes / sizeOfElement = 40 / 4 = 10
LIVE EXAMPLE
Note that if you pass an array to a function, the above won't work since the array decays to a pointer and sizeof(array) returns the size of the pointer.
std::size_t function(std::uint32_t a[]) // same for void function(std::uint32_t a[10])
{
return sizeof(a); // sizeof(std::uint32_t*)!
}
std::uint32_t array[10];
auto sizeOfArray = function(array); // array decays to a pointer inside function()
LIVE EXAMPLE #2
As it is described in the C++ Standard (5.3.3 Sizeof)
1 The sizeof operator yields the number of bytes in the object
representation of its operand. The operand is either an expression,
which is an unevaluated operand (Clause 5), or a parenthesized
type-id.
In this expression
sizeof(arr) / sizeof(arr[0])
there are used two subexpressions with the sizeof operator.
This subexpression
sizeof(arr)
yields the number of bytes occupied by array arr (I suppose that arr is an array).
For example if you declared an array like
int arr[10];
then the compiler has to reserve memory that to hold 10 elements of type int. If for example sizeof( int ) is equal to 4 then the compiler will reserve 10 * 4 = 40 bytes of memory.
Subexpression
sizeof(arr[0])
gives the number of bytes occupied by one element in the array. You could use any index as for example
sizeof(arr[1000])
because the expression is unevaluated. It is only important the size in bytes of the object (an element of the array) used inside the operator.
Thus if you know the total bytes that were reserved for an array
sizeof(arr)
and know how many bytes each element of the array occupies (all elements of an array have the same size) then you can calculate the number of elements in the array by using the formula
sizeof(arr) / sizeof(arr[0])
Here is a simple relation. If you have an array of N elements of type T
T arr[N];
and you know the size of the memory occupied by the array then you can calculate the size of its element by using formula
sizeof( arr ) / N == size of an element of the array.
And vice verse
If you know the size of the memory occupied by the array and the size of its element you can calculate the number of elements in the array
sizeof( arr ) / sizeof( a[0] ) == N - number of elements in the array
The last expression you can rewrite also the following way
sizeof( arr ) / sizeof( T ) == N - number of elements in the array
because the elements of the array have type T and each element of the array occupies exactly the number of bytes that are required to allocate an object of type T.
Take into acccount that usually beginners make such an error. They pass an array as an argument to a function. For example let's assume that you have a function
void f( int a[] )
{
// ...
}
And you pass to the function your array
int arr[10];
f(arr);
then the function uses the pointer to the first element of the array. In fact the function has declaration
void f( int *a )
{
// ...
}
So if you write for example within the function
void f( int *a )
{
size_t n = sizeof( a ) / sizeof( a[0] );
// ...
}
then as a within the function is a pointer (it is not an array) then you will get something like
void f( int *a )
{
size_t n = sizeof( int * ) / sizeof( int );
// ...
}
Usually the size of a pointer equal to either 8 or 4 bytes depending of the used environment. And you won't get the number of elements. You will get some weird value.
int - is equal to 4 bytes
sizeof(int) it means: 1 * 4 = 4
int arr[10] - is holding 10 int
sizeof(arr) it means: 10 * 4 = 40, we got 10 int and every int got 4 bytes,, arr without the [] it means all the arr.
sizeof(arr[0]) it means: 1 * 4 = 4
sizeof(arr) / sizeof(arr[0]) = 10*4 / 1*4 = 10,, and it is the length of the array.
It only works if arr has not been decayed into a pointer, that is, it is an array type, not a pointer type.
sizeof(arr) is the total size occupied by the array.
sizeof(arr[0]) is the size of the first element in the array. (Note that zero length arrays are not permitted in C++ so this element always exists if the array itself exists).
Since all the elements will be of the same size, the number of elements is sizeof(arr) / sizeof(arr[0]).
When dealing with an array (some_type name[some_size]) sizeof(name) is how many bytes the array occupies. Dividing the total size of the array by the size of one element (sizeof(name[0])) gives you how many elements are in the array.
c++ way to use extent, which allows u to get a number of elements in Nth dimension of the array.
see http://en.cppreference.com/w/cpp/types/extent for details
int values[] = { 1 };
std::extent<decltype(values)>::value == 1
Let's take an example like the arr[]={1,2,4,3,5}.
Then the size of the array will be 5 and the size of arr[0] will be "1" BECAUSE it consists of an element in it. Basically it's a subarray the from the above problem it will be 5/1 it will automatically returns the size of array =5.
The difference is
int arr[5] = {1,2,3,4,5};
here arr is Pointer to array and &arr[0] is pointer of type Integer

Multi-dimensional arrays and pointers in C++

Let's say I declare and initialize the following multi-dimensional array in C++:
unsigned a[3][4] = {
{12, 6, 3, 2},
{9, 13, 7, 0},
{7, 4, 8, 5}
};
After which I execute this code:
cout << a << endl; // output: 0x7fff5afc5bc0
cout << a + 1 << endl; // output: 0x7fff5f0afbd0
cout << *a << endl; // output: 0x7fff5afc5bc0
cout << *a + 1 << endl; // output: 0x7fff5f0afbc4
I just don't understand what is happening here.
a is the address of the first element, right? In single-dimensional arrays, *a should be the value of the first element, but instead it's the same as a?! What does *a even mean in this context?
Why is a + 1 different from *a + 1?
You should try and find some good documentation about pointers, arrays, and array-to-pointer decay. In your case, unsigned a[3][4] is a bi-dimensional array of type unsigned [3][4]. Whenever you refer to it as a, it decays to a pointer to unsigned[4], so the decayed type of a is unsigned (*)[4]. Therefore dereferencing it gives you an array, so *a is the array [12, 6, 3, 2] (technically it's the pointer to the first element into the array).
Now, a+1 means "increment the pointer to unsigned[4] by 1", in your case it "jumps" 4 unsigneds in the memory, so now a+1 points to the "row" indexed by 1 in your example. Dereferencing it *(a+1) yields the array itself ([9,13,7,0]) (i.e. the pointer to the first element of it), and dereferencing again gives you the first element, i.e. **(a+1) equals 9.
On the other hand, *a+1 first dereferences a, so you get the first row, i.e. [12,6,3,2] (again, technically the pointer to the first element of this row). You then increment it by one, so you end up pointing at the element 6. Dereferencing it again, *(*a+1), yields 6.
It may be helpful to define a equivalently as
typedef unsigned T[4]; // or (C++11) using T = unsigned[4];
T a[3]; // Now it's a bit more clear how dereferencing works
Two dimensional array is array of array.
You can visualize a as
a = { a[0], a[1], a[2]}
and a[0], a[1], a[2] as
a[0] = { a[0][0], a[0][1], a[0][2], a[0][3]};
a[1] = { a[1][0], a[1][1], a[1][2], a[1][3]};
a[1] = { a[2][0], a[2][1], a[2][2], a[2][3]};
Analysis of your first question
a is the address of the first element, right?
Yes a is the address of the first element, and first element of a is a[0] which is the address of the first element of a[0][0].
*a should be the value of the first element, but instead it's the same as a?
Yes *a should be the value of the first element that refer a[0]. And we see a[0] is the address of a[0][0] so as a . Thus *a have same value as a which is the address of a[0][0].
What does *a even mean in this context?
Previously answered, *a is the address of first arrays first element a[0][0], and *(a+1) is the address of second arrays first element a[1][0].
And analysis of your second question
Why is a + 1 different from *a + 1?
At this time perhaps you can answer your owns question.
a is the address of a[0] then
a+1 is the address of a[1] which hold address of a[1][0].
You can print the value by
cout<<**(a+1)<<endl; // 9
Other way *a is the value of a[0] which is the address of a[0][0].
So *a+1 is the address of a[0][1]. You can print the value as
cout<<*(*a+1)<<endl; // 6

Pointer syntax usage in Array

I have some problem understanding the pointers syntax usage in context with two dimensional arrays, though I am comfortable with 1-D array notation and pointers, below is one of the syntax and I am not able to understand how the following expression is evaluated.
To access the element stored at third row second column of array a we will use the subscripted notation as a[2][1] other way to access the same element is
*(a[2]+1)
and if we want to use it as pointers we will do like this
*(*(a+2)+1)
Though I am able to understand the replacement of *(a[2]+1)
as *(*(a+2)+1) but I don't know how this is getting evaluated.
Please explain with example if possible.
Assume array is stored in row wise order and contain the following elements
int a[5][2]={
21,22,
31,32
41,42,
51,52,
61,62
};
and base address of array is 100(just assume) so the address of a[2] is 108 (size of int =2(another assumption)) So the expression *(*(a+2)+1). How does it gets evaluated does it start from the inside bracket and if it does then after the first bracket we have the value to which 1 is being added rather than the address... :/
To start of with
a[i] = *(a+i);
So
a[i][j] = *(a[i] +j)
and
a[i][j] = *(*(a+i) + j)
How a[i] = *(a+i):
If a is a array then the starting address of the array is given by &a[0] or just a
So when you specify
a[i] this will decay to a pointer operation *(a+i) which is, start at the location a and dereference the pointer to get the value stored in the location.
If the memory location is a then the value stored in it is given by *a.
Similarly the address of the next element in the array is given by
&a[1] = (a+1); /* Array decays to a pointer */
Now the location where the element is stored in given by &a[1] or (a+1) so the value stored in that location is given by *(&a[1]) or *(a+1)
For Eg:
int a[3];
They are stored in the memory as shown below:
a a+1 a+2
------------------
| 100 | 102 | 104|
------------------
&a[0] &a[1] &a[2]
Now a is pointing to the first element of the array. If you know the pointer operations a+1 will give you the next location and so on.
In 2D arrays the below is what the access is like :
int arr[m][n];
arr:
will be pointer to first sub array, not the first element of first sub
array, according to relationship of array & pointer, it also represent
the array itself,
arr+1:
will be pointer to second sub array, not the second element of first sub
array,
*(arr+1):
will be pointer to first element of second sub array,
according to relationship of array & pointer, it also represent second
sub array, same as arr[1],
*(arr+1)+2:
will be pointer to third element of second sub array,
*(*(arr+1)+2):
will get value of third element of second sub array,
same as arr[1][2],
A 2D array is actually a consecutive piece of memory. Let me take a example : int a[3][4] is representend in memory by a unique sequence of 12 integer :
a00 a01 a02 a03 a04 a10 a11 a12 a13 a14 a20 a21 a22 a23 a24
| | |
first row second row third row
(of course it can be extended to any muti-dimensional array)
a is an array of int[4] : it decays to a pointer to int[4] (in fact, it decays to &(a[0]))
a[1] is second row. It decays to a int * pointing to beginning of first row.
Even if arrays are not pointer, the fact that they decay to pointers allows to use them in pointer arithmetic : a + 1 is a pointer to second element of array a.
All that explains why a[1] == *(a + 1)
The same reasoning can be applied to a[i] == *(a+i), and from there to all the expressions in your question.
Let's look specifically to *(*(a+2)+1). As said above, a + 2 is a pointer to the third element of an array of int 4. So *(a + 2) is third row, is an array of int[4] and decays to a int * : &(a[2][0]).
As *(a + 2) decays to an int *, we can still use it as a base for pointer arithmetic and *(a + 2) + 1 is a pointer to the second element of third row : *(a + 2) + 1 == &(a[2][1]). Just dereference all that and we get
*(*(a + 2) + 1) == a[2][1]