Determining the difference of row elements in 3d array - c

I need to know if there is 3 d array say :
int a[2][3][2]={{{1,2},{9,8},{3,7}},{{2,2},{1,4},{5,4}}};
How And what does the expression a[1]-a[0] calculate?

what does the expression a[1]-a[0] calculate?
It calculates the difference between the pointers to which a[1] and a[0] decay if use as operators to the arithemtic operator -.

#include <stdio.h>
int main(void){
int a[2][3][2]={{{1,2},{9,8},{3,7}},{{2,2},{1,4},{5,4}}};
printf("%d\n", (int)(a[1]-a[0]));//3
int (*b1)[2] = a[1];//b1 point to {1,2}
int (*b0)[2] = a[0];//b0 point to {2,2}
printf("%d\n", (int)(b1-b0));//3
printf("%d\n", (int)(&a[1]-&a[0]));//1
return 0;
}
/*
int a[2][3][2]
a <-> int (*)[3][2]
a[n] <-> int [3][2] <-> int (*)[2]
&a[n] <-> int (*)[3][2]
*/

Always think of multidimensional arrays as a grid/table. Here is that same array split up into sections:
a[2] = Container containing 2 2D arrays
[3] = Container containing 3 arrays
[2] = Actual data values
What data you are accessing all depends on how many brackets you are putting when you call the array, for example:
a[1] = {{2, 2},{1, 4},{5, 4}}
a[1][1] = {1, 4}
a[1][1][1] = 4
The expression a[1] - a[0] can't be done because you are subtracting an array by another array, which means you are using objects that point to data, not actual data. But, it literally evaluates to:
a[1] = {{2, 2},{1, 4},{5, 4}} and
a[0] = {{1, 2},{9, 8},{3, 7}} so,
{{2, 2},{1, 4},{5, 4}} - {{1, 2},{9, 8},{3, 7}}

Related

Why *pointer_name behaves differently in 1D and 2D array

Why is it that when *q is used in 1D array it gives the value in the array whereas *p in 2D array gives an address instead. Isn't *pointer_name supposed to tell what is stored, so why is output an address instead of 40 (the value in array)?
#include<stdio.h>
int main(){
int a[3][4] = {
{40, 1, 2, 3} ,
{4, 5, 6, 7} ,
{8, 9, 10, 11}
};
int (*p)[4] = a;
int b[4] = {3,4,8,5};
int *q = b;
printf("%d, %d",*q, *p);// output- 3, 10485040
return 0;
}
Because p is a pointer to an array. When you dereference p the array will decay to a pointer to the first element. Doing *p and &(*p)[0] is equivalent (and also equivalent to &a[0][0]).
If you want to print the first element then you need to dereference both pointers, i.e. **p.
2D array means an array of arrays! so each slot of first row in the 2D array should have the address of another array.
for instance if you have an array a[2][3] , the a[0] value is the address of the first slot of an array with size 4. and a[1] like so etc .

What is the difference between these two C declarations

I declared and initialized a 2x2 array as follows:
int arr[2][2] = {1, 2, 3, 4};
Then, a pointer to integer:
int *p1;
Initialize the pointer as:
p1 = arr[0]; //p1 points to {1, 2}
Now I can print elements using p1 as *p1
Now, when I declare:
int (*ptr)[2][2];
ptr = &arr;
To print the elements, now I have to use:
printf("%d\n", *(**(ptr)+1));
What is the difference between these two declarations?
int (*ptr)[2][2]; is a pointer to a 2x2 matrix, not a pointer to an int. Since each dimension of a matrix behaves somewhat like a pointer, that is why you need extra dereferencing in the printf.

Array Assignments in C Using Pointer Arithmetic

How can I change the value in an array when I access a particular element using pointer arithmetic?
#include <stdio.h>
int main() {
int a[3] = {1, 1, 1}, b[3] = {2, 2, 2};
a++ = b++; // How can I get this to work so a[1] = b[1]?
return 0;
}
Arrays are not pointers. Repeat this three times; arrays are not pointers.
You cannot increment an array, it is not an assignable value (i.e., you cannot mutate it). You can of course index into it to get a value back:
a[1] = b[1];
Secondly, your current code is attempting to increment and then assign a new value to the array itself, when you meant to assign to an element of the array. Arrays degrade to pointers when required, so this works too:
int *a_ptr = a;
int *b_ptr = b;
*++a_ptr = *++b_ptr;
// or, better...
a_ptr[1] = b_ptr[1];
Which is what you meant to do. I prefer version 1 and, more often than not, use indexing with pointers as well because it is often easier to read.
How can I get this to work so a[1] = b[1]?
Simple:
a[1]++;
if you just wanted to increment a[1] (1) to be what b[1] happens to be (2), or
a[1] = b[1];
if you want a[1] to have the same value as b[1] regardless of what that value is.
when I access a particular element using pointer arithmetic?
In your example, you are not accessing any element, nor are you doing pointer arithmetic because a and b are arrays, not pointers. The formulation of your question is difficult to interpret, both because of that and because
a++ = b++;
1) is completely meaningless 2) would not be legal C even if a and b were pointers, because the left side must be an lvalue, but a++ is not 3) is not discernably related to your wish for a[1] to be the same as b[1]. Possibly what you want is:
int* ap = a; // get pointer to first element of a
int* bp = b; // get pointer to first element of b
// point ap to second element of a and
// point bp to second element of b and
// copy the value at *bp to *ap
*++ap = *++bp;
That would indeed set a[1] to b[1].
Your arrays in this case are not actually pointers. They are converted by the compiler when they are accessed as pointers, but I don't believe that you're allowed to do something like a++.
If you want to do this with arithmetic, you'll need actual pointers:
int *ap = a, *bp = b;
*ap++ = *bp++;
That is like doing a[0] = b[0]; and then moving each pointer to the next element in their associated array.
But your question says you want to set a[1] = b[1]. Well, you could do this:
*++ap = *++bp;
Or you could just use the array indices and make it much more obvious what you're doing.

Array of Pointers in C?

int b[3][2] = { {0, 1}, {2, 3}, {4, 5} };
int (*bpp)[2] = b;
int *bp = b[0];
At the above code: Is *bpp a pointer to a two-dimensional array? Or an array of pointers with the length of 2? Why is *bpp surrounded with parenthesis? Is there a difference between *bpp[2] and (*bpp)[2] ?
Meantime, in the following code: (Changing the dimension of the array)
int i[4] = { 1, 2, 3, 4 };
int (*ap)[2] = (int(*)[2])i;
The second line is very confusing to me, especially the typecasting (int(*)[2]), what data type is it exactly casting to?
Thank you ^^
bpp is a pointer to an array of two int. *bpp is an array of two int. int *bpp[2] would declare bpp as an array of two pointers to int (this parentheses make it be a pointer to an array of two int).
(int(*)[2]) is a cast to a pointer to an array of two int.
These can be read by considering the "declaration follows use" rule (combined with knowledge of operator precedence):
dereference (so bpp is a pointer)
|
v
int (*bpp)[2]
^ ^
| |
| array index (so the thing that bpp points to is an array)
|
the thing on the left is the final type... here it is int,
so the array is an array of int

passing the array inside a function

int f(int b[][3]);
int main()
{
int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
f(a);
printf("%d\n", a[2][1]);
}
int f(int b[][3])
{
++b;
b[1][1] = 1;
}
3x3 => 9 elements contained in the 2-D array a. When it's passed, then b will contain the the base address of the a. If suppose base address is 1000 then ++b how does it to 3 locations and not 9 locations ahead? Are we doing typecasting when the variable a is passed to b[][3] as only the three elements?
How does b[1][1] correspond to the address of 8 and not 5?
We can't do incrementing or decrementing in an array as array is a const pointer, but how is that they are incrementing ++b as its an array?
The function heading
int f(int b[][3])
is a nothing more than a confusing way to write (and is exactly equivalent to)
int f(int (*b)[3])
The type of b is "pointer to three-element array of int". When you increment the b parameter you adjust it to point to the next three-element array of int -- now it points to {4,5,6}. Then b[1] indexes once more and gives you the array {7,8,9} and finally b[1][1] gives you the oneth element of that array, namely 8.
C multidimensional arrays are really linear, except that there is syntactic sugar to do the arithmetic correctly.
so with b[][3], it excepts a 1-D array and implicitly translates b[i][j] --> b[3*i+j]
++b works as follows: (++b)[i][j] = ORIGINAL_b[i+1][j]. So in your case, you are accessing ORIGINAL_b[1+1][1] = ORIGINAL_b[2*3+1] = ORIGINAL_b[7] (the 8th element)
Note: this is in stark contrast to the dynamic malloc version (in **b, b is a array of pointers)
How is b[1][1] corresponds to the address of 8 and not address of 5?
This is expected behavior:
int f(int b[][3])
{
//at this point b[0][0] is 1, b[1][1] is 5
++b;
//now b[0][0] is 4, b[1][1] is 8
b[1][1]=1;
}
The pointer has incremented to point to the next memory slot, which is the second slot of array a. Basically:
b -> a[0]
++b -> a[1]

Resources