two dimensional Arrays access using pointers - c

Is
*(ary[3]+8)
and
ary[3][8]
are the same ? If yes, please explain how ? ary[3] returns the address of first element or the value in ary[3][0] ? ary is a two dimensional array.
Thanks in advance.

Yes
a[i] is same as *(a+i)
ary[i][j] is same as *( *(ary+i)+j))

If x is an array (int, say) x[i] is just a syntactic sugar for *(x+i). In your case, ary is a two-dimensional array (again of int, say). By the same syntactic sugar mechanism, ary[i][j] is equivalent to *((*(ary+i))+j), from which it is clear what happens under the hood.

*(ary[3]+8) says value at 8th column of third row.ary[3] is base address of third Row.ary[3][8] will also access to same element at third row and 8th column.
For Example i am taking an 2D array of two row and 4 column which is equivalent to 1D array of 8 elements.As shown below.
int a[8] = {0,1,2,3,4,5,6,7};
int b[2][4] = {{0,1,2,3},{4,5,6,7}};
since b is 2D array , so you can consider it as array of two 1D arrays.when you pass b[1] or b[1][0] it says address of first row.Rectangular array allocated in memory by Row.so if you want to find address of element a[row][col] it will get calculated as
address = baseAddress + elementSize * (row*(total number of column) + col);

As others already have said, a[i] is just a sugar for *(a+i).
I just would like to add that it always works, that allows us to do things like that:
char a[10];
char b;
char c[10][20];
// all of these are the same:
b = a[5]; // classic
b = *(a + 5); // pointer shifting
b = 5[a]; // even so!
b = c[5][9];
b = *(c[5] + 9);
b = *(*(c + 5) + 9);
b = *(c + 5)[9];
b = 5[c][9];
b = 5[9][c]; // WRONG! Compiling error

Related

Two dimension array dereferencing not working

Hello I am learning c in school and having a little confusion on this problem.
That is,
b is two d array, and I am trying to implement around printing values and the adress,
but why is *(b+1) giving the same thing as b+1?
I thought *(b+1) would give the value of the first element of the second row.
and if I change printf("%p\n", *(b+1)) to printf("%d\n", *(b+1)), it just gives a garbage value.
Why is it working like this?
I appriciate any feedback! thank you
int main()
{
int b[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
printf("b:\n");
print_2d_array(3, 4, b);
printf("\n");
printf("%p\n", b);
printf("%p\n", *(b+1));
printf("%p\n", b+1);
return 0;
}
Output is like this,
b:
0 1 2 3
4 5 6 7
8 9 10 11
0x7ffeecee6730
0x7ffeecee6740
0x7ffeecee6740
The question you have asked essentially boils down to a question about the nature of an array and the address of an array, which is a fairly well covered topic (see this for example). However, you likely confused yourself with the pointer arithmetic, so this answer tries to clarify some of that.
In C, when array object is used in an expression, its value and type becomes the same as the pointer to its first element.
In your case, you have:
int b[3][4] = { /* ... */ };
/* ... */
printf("%p\n", *(b+1));
printf("%p\n", b+1);
If we consider the last print statement,b in the expression b + 1 becomes the same as &b[0] + 1, and this would be the same as &b[1].
When we consider the print statement before the last one, we note that *(b+1) is defined to be the value b[1]. However, the result of that expression is an array of 4 int. That array now takes on the value and type of its first element, which would be &b[1][0].
Since you need to be able to find the address of the first element of an array from the array itself, the address of an array, &b[1], has the same pointer value as the address of its first element &b[1][0].
However, &b[1] and &b[1][0] have different types. The former is a pointer to an array, while the later is a pointer to an int.
For additional information, I encourage you to read the linked question at the top of this answer for more about arrays and the address of arrays.
*why is (b+1) giving the same thing as b+1?
The output address is numerically same but their type is different.
The type of *(b+1) is int [4] whereas the type of b+1 is int (*)[4].
*(b+1), when used in an expression, will convert to address of first element of second row1):
*(b + 1) -> b[1] -> ((b[1]) + (0)) -> &(*((b[1]) + (0))) -> &b[1][0]
and b+1 will give address of second row.
Address of an array and address of first element of that array are numerically same but their type are different.
*I thought (b+1) would give the value of the first element of the second row.
*(b+1) will give the second element of 2D array b which is nothing but a 1D array of 4 integers.
To access the first element of second row using *(b+1), you can do:
(*(b+1))[0]
To access the second element of second row using *(b+1), you can do:
(*(b+1))[1]
third element ....
(*(b+1))[2]
and so on .....
Note that *(b+1) is equivalent to b[1]1). So,
(*(b+1))[0] is equivalent to b[1][0]
(*(b+1))[1] is equivalent to b[1][1] .. and so on
Hope this clarifies your doubt.
1 ) From C Standards#6.5.2.1
The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2)))..

Multi-dimensional array access using pointer in C

Note that this has probably been answered before, but now in a way that I could understand it.
I'm trying to understand how pointers and arrays work together. I thought I understood both how and why 1D and 2D arrays could be accessed with pointers until I tried to wrap my head around 3D arrays (just to be clear, I understand 3D arrays, just not how to access them with pointers).
So let's say I have an array x[5] and I want to access the element x[1] using pointers. In that case, I can use *(&x[0]+1), because x is the same as &x[0] and *(x + 1) can be used to access a[1].
Now, for a 2D array, let's say it is declared as x[5][3].
To access x[1][2], I can use *(&x[0][0]+3*1+2). I can kind of understand this. We start at memory location x[0][0], then add 3 * 1 to get from x[0][0] to x[1][0], and then add 2 to get from x[1][0] to x[1][2].
The above makes sense to me until I get to a three dimensional array. Let's assume that x is declared as x[3][4][5], how would I get to, let's say element x[2][1][3] using the same logic(if possible)? Also, how can I apply this logic to higher dimensional arrays as well?
Any advice on this is greatly appreciated!
Supposing you have the following array:
//x[i][j][k]
int x[2][3][5] = { {{0,1,2,3,4},
{5,6,7,8,9},
{10,11,12,13,14}},
{{ 88,1,2,3,4 },
{ 5,6,7,8,9},
{ 10,11,12,77,14}}
};
Elements of 3D array are arranged in series in the memory like this:
{0,1,2,3,4},{5,6,7,8,9},{10,11,12,13,14},{ 88,1,2,3,4 },{ 5,6,7,8,9},{ 10,11,12,77,14}
Obviously, If you hava the address of the first element you can access the others by adding an offset. The address of the first element is **x, and the address of the next one is **x+1 and so forth. To access the elements of the x array look at the following example:
int D3_width = sizeof(x)/sizeof(x[0]); //2
int D2_width = sizeof(x[0]) / sizeof(x[0][0]); //3
int D1_width = sizeof(x[0][0]) / sizeof(int); //5
int i = 0, j = 2, k = 3;
cout << *(**x + i*D2_width*D1_width + j*D1_width + k);
output:13
You can use the same approach for other multi-dimensional arrays.
The formula is tested and works perfectly.
For a two-dimensional array you can skip through indexes of rows with pointer arithmetic as you were doing:
First index of first row + (length of row * desired Row)
If you are making your way up the dimensions, this expression will start to get rather large.
For 3D:
First index of first plane + (size of plane * desired plane)
Note that the plane is a 2-dimensional structure.
Now moving into 4D:
First index of first cube + (size of cube * desired cube )
Hope you get the idea.

creating 2 dimensional array of unspecified (varying) size

Newbie question: I want to dynamically create an integer 2D array M[i,j], whose sizes (in both dimensions) are unknown beforehand. Moreover, for each index i, the size of the i-th row may vary.
Question 1: How do I declare such an array (do I even have to)? I have tried Array[], Array(Int64,1...), and Array((Int,Int),0)as in this hint and others.
Question 2: once created, how to I populate the array in a smart and concise way? Say my i-th row is suppose to be equal to a given 1-dimensional B, I would like to write
A[i] = B
or
A[i,:] = B
or even
A[i,1:n] = B
where n is the size of B. All of these give me a BoundsError(). Slicemight do the trick, but I cannot make it agree with my declaration.
You don't want a 2D array here, because in a 2D array all rows are of the same size. Instead, you want a vector-of-vectors. For example:
A = Array(Vector{Int}, 5)
A[1] = rand(1:10, 3)
A[2] = rand(1:100, 22)
If you inspect A, you'll see something like this:
julia> A
5-element Array{Array{Int64,1},1}:
[5,7,7]
[1,63,40,86,61,39,98,5,68,97 … 78,49,44,89,48,63,90,90,86,83]
#undef
#undef
#undef
Another great tool is to use a comprehension:
julia> A = Vector{Int}[ [1:m] for m = 1:5]
5-element Array{Array{Int64,1},1}:
[1]
[1,2]
[1,2,3]
[1,2,3,4]
[1,2,3,4,5]
The main thing you'll want to be careful about is that each element of A is a reference to a vector; if you assign
A[1] = b
A[2] = b
then any change to b will affect both A[1] and A[2]. If you don't want that, use
A[1] = copy(b)
A[2] = copy(b)

C : explain theory behind

I have minimal experience with C, but have been asked to convert a C program into R. There is one bit troubling me:
I have a function that takes an int
int a
and within the function i have an array:
double b[3] = {
1.8293,
-0.592,
2.3330,
}
and later on in the function i have:
c = b[a];
can someone tell me what this line is doing? what is being assigned to c? is it simply an array of size b, where all the values of b have been multiplied by a?
Thanks.
c is assigned with the a th value of array b[].
if a is equal to 1 then c will be equal to -0.592
if a contains 0 then c = b[a] means that the first element of the array b[] is assigned to a, without changing array b
The variable a here is an index into the array. For example if a=0, then b[a] is the first element (1.8293 in this case).
In general b[a] extracts out a particular element from the array.
So here's a mock up of your function as you described it (I made up the parts you failed to mention) I added comments // to explain what is going on:
void foo(int a)
{
// define an array of 3 doubles
//b[0] = 1.8293
//b[1] = -0.592
//b[2] = 2.333
double b[3] = { 1.8293, -0.592, 2.3330 };
double c; // Note c is a double, because we're going to assign
// one of the values from b
//we're going to use a to access array b, that means a has to be 0, 1, or 2
if(a < 3)
c = b[a];
//Now c is set to one of those three values in b
//(depending on what value a has)
return;
}
The a'th element of the double array b is assigned to c (the first element has index 0).
you need to make some step in C learning.
b[a] means that you will get the content of element with index a from b array

How to access any element in a 2D array in C using pointer?

I want to access an element in a 2D array in C using pointer
for example (this using traditional way)
multi[0][1] = ....
I tried this way
*(*(multi+0)+1) = ....
But it gives me an error saying
" pointer required "
So what am i suppose to do?
Actually this is what I was doing
void state_array(int *pointer , int *multi){
int i ;
for ( i = 0 ; i < 4 ; i++){
*(*(multi + i) + 0 )= *(pointer+i) ;
}
for ( i = 4 ; i < 8 ; i++){
*(*(multi + i ) + 1 )= *(pointer+i) ;
}
for ( i = 8 ; i < 12 ; i++){
*(*(multi + i ) + 2 )= *(pointer+i) ;
}
for ( i = 12 ; i < 16 ; i++){
*(*(multi + i ) + 3 )= *(pointer+i) ;
}
}
There is no problem with ((multi+0)+1). It will work. Please specify full code to find out the error.
Refer the link
The reason that you get that particular error message is that the variable multi is type int *, and not int **. Your function treats it as an int ** by dereferencing it twice in *(*(multi + i ) + j)
Break the expression down:
*(multi + i) dereferences the pointer multi+i. Because multi is type int *, this is fine. The resulting type is int.
*( ... + j) attempts to dereference ... + j. The problem is that ... is type int, and ... + j is type int. Your cannot dereference an int (it's an integral type, not a pointer).
Two solutions:
Declare multi to be type int **, and pass in an actual int **
Keep multi as an int * and use single-index addressing
Solution 1 only works if you allocate an array of int * and then fill it to point to arrays of int. It will not work if you declare a multidimensional array in C (i.e., int myarray[23][78]). In C, a declared multidimensional array is kept in contiguous memory, and this information is lost if you pass it to a function as a pointer-to-a-pointer.
The second solution is to choose either row-major or column-major indexing, and the pass in the relevant sizes. You should probably be doing this anyway. If you choose row-major indexing (rows are contiguous in memory), an M x N matrix multi is addressed as
multi[i + M*j]
If you choose column-major indexing (columns are contiguous in memory), the same matrix is addressed as
multi[N*i + j]
This solution will work for statically-declared multidimensional arrays in C, and allows you to dynamically allocate a multidimensional array in C with minimal overhead.
Also, be aware that statically-declared multidimensional arrays in C uses column-major indexing when they're accessed as mat[i][j]. However, if you're doing serious matrix work, there are good reasons to prefer row-major indexing. Finally, Fortran uses row-major indexing, and if your code needs to interface with Fortran (as numerical code often does), you should probably prefer row-major indexing.

Resources