output of p[-2] in C array [duplicate] - c

This question already has answers here:
What does s[-1] = 0 mean?
(6 answers)
Closed 8 years ago.
I was trying the below code snippet. Please help me in understanding how the o/p is coming as 2? What does p[-2] mean here?
int main(void){
int ary[4] = {1, 2, 3, 6};
int *p = ary + 3;
printf("%d\n", p[-2]);
}

ary is an array of four ints. This will be put in memory like this:
| 1 | 2 | 3 | 6 |
^ ^ ^
| | |
ary p - 2 p
By saying p = ary + 3, you're setting p to the address of the fourth element in the array. So, p is pointing to 6. p[-2] is equal to *(p - 2). That means you point p to the second element in the array, and access its value: 2.

int *p = ary + 3 points to ary[3] so if you move the pointer two steps back you will get ary[1]

Related

Converting multidimensional arrays to pointer notation [duplicate]

This question already has answers here:
Pointer address in a C multidimensional array
(5 answers)
Closed 2 years ago.
For the following value-of an array, I can do:
array[i][j][k] = *(*(*(array+i)+j)+k);
---------------------------------
int xar[3] = {1,2,3};
printf("%d | %d\n", xar[1], *(xar+1));
int xar2[2][3] = {{1,2,3}, {4,5,6}};
printf("%d | %d\n", xar2[1][2], *(*(xar2+1)+2));
int xar3[2][2][2] = {
{{1, 2},{3, 4}},
{{5, 6}, {7, 8}}
};
printf("%d | %d\n", xar3[1][1][1], *(*(*(xar3+1)+1)+1));
2 | 2
6 | 6
8 | 8
However, I'm having a tougher time trying to get the address of an array element and why that works, for example, if I have:
&array[i][j][k];
array+i gives me the equivalent of &array[i], but then how would I grab the full inner item?
Note that &*array will cancel each-other out, so we can do:
array[i][j][k] = *(*(*(array+i)+j)+k);
&array[i][j][k] = &*(*(*(array+i)+j)+k); // &* can be eliminated
&array[i][j][k] = *(*(array+i)+j)+k;

Make 1D array addressable with row and column

I am writing a chess engine using an array (single dimension) in C?
#define ROW(sq) (sq >> 3)
#define COL(sq) (sq & 7)
int board[64] = {
0,1,2,3,4,5,6,7,
8,9,10,11,12,13,,14,15,
.......................
.......................
56,57,48,59,60,61,62,63
}
Now:
To get the row and col of number 11 I use this:
int r = ROW(11);
int c = COL(11);
It gives:
r = 1
c = 3
Please help me to write a function so that it takes the parameter as r and c and gives the correct square like:
sq = fnc(r,c);
sq = fnc(1,3);
sq = 11;
You just have to calculate row * MAX_COL + col where MAX_COL = 8. With row * MAX_COL you will go into the next row, like the following figure shows:
1 * 8 --- 2 * 8 ---
| |
| row = 0 | v row = 1 | v row = 2
| 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 | 16 ...
If you want a macro which uses the global variable board:
#define FIELD(row,col) board[(row) * 8 + (col)]
or as function which also uses the global defined board variable:
inline int FIELD (int row, int col)
{
return board[row * 8 + col]
}
if you want to pass the board as array to the function you can do the following, where int boardArr[] decays to a pointer:
inline int FIELD (int boardArr[], int row, int col)
{
return boardArr[row * 8 + col]
}
Also you should change your macro definitions, because they are unsafe if the parameter that is passed is a value that is used in a calculation. You can read it here on SO. So you should use braces around the parameters sq:
#define ROW(sq) ((sq) >> 3)
#define COL(sq) ((sq) & 7)
It would be even better to use inline functions as it is also said in the SO answer.
If your board is always 8x8, you can see that each r starts at 0, 8, 16... and each c is just the offset from those initial points, so given an r and c, you can calculate the array index by board[(r * 8) + c] to get the corresponding piece.
This is best approached using a two-dimensional array because that way you can simply access board[r][c].
If you (or your professor) insist on a one-dimensional array, this macro will do what you want:
#define GET_PIECE(r, c) (board[((c) + (8) * (r))])
Notice how everything is wrapped in parentheses. This is very important with macros!
A better solution would be to use an inline function.

How does `*((*arr+(i*3))+j)` work when printing a 2D array `arr`?

Code:
#include <stdio.h>
int main(void)
{
int arr[2][3] = {{1,2,3},{4,5,6}};
int i, j;
for(i = 0; i < 2; i++)
{
for(j = 0; j < 3; j++)
{
printf("%d ", *((*arr+(i*3))+j));
}
printf("\n");
}
return 0;
}
I'm surprised how the above code gives the output:
1 2 3
4 5 6
I know that *(arr+i) == arr[i] and also that I should be using arr[i][j] instead of making everything more complicated, but I don't understand how *((*arr+(i*3))+j) works.
In my understanding, *((*arr+(i*3))+j) can be simplified to *((*arr)+(i*3)+j) since the *(indirection operator) has the most precedence here.
So, when i is zero and j iterates through, 0 to 2, the expression is the same as arr[0][j] which prints the integers of the first subarray.
My confusion builds up when i becomes 1. The next three expressions will be *((*arr)+(1*3)+0), *((*arr)+(1*3)+1) and *((*arr)+(1*3)+2) which can be simplified to arr[0][3], arr[0][4] and arr[0][5].
How does this print the last three values?
int arr[2][3] = {{1,2,3},{4,5,6}};
In memory :
1 | 2 | 3 | 4 | 5 | 6
each number on an adjacent memory "cell" the size of an int, in this order
Second line :
i = 1
j = 0
*((*arr+(i*3))+j)) means *((*arr + 3) + 0)-> *({1, 2, 3} + 3) -> *({4, 5, 6}) = 4
Keep in mind that x[n] is equivalent to *(x + n), whatever x or n. (This also means arr[1] is equivalent to *(arr + 1), *(1 + arr) and so 1[arr] which I find funny)
Here arr[1][0] : x is arr[1] and n is 0 so first equivalence: *(arr[1] + 0)
Second x is arr and n is 1 so *(*(arr + 1) + 0).
Finally arr + 1 means the adress at arr + sizeof(*arr), which means:
(arr + 1) is equivalent to (*arr + 3) because *arr is arr[0] which is of type int[3]
The C language stores multidimensional arrays in what is called row-major order,
so when you declare int arr[2][3] the memory is actually laid out with the entries of the array occurring adjacent to each other in
memory in this sequence:
arr[0][0] arr[0][1] arr[0][2] arr[1][0] arr[1][1] arr[1][2]
This has a couple of consequences that are useful to know:
arr[1] acts like a pointer to a one-dimensional array. just as it does when you declare int **arr;.
The initializers in your initialization list are copied into memory locations in exactly the order you list them.
The array is stored in your memory like :
_____ _____ _____ _____ _____ _____
| 1 | | 2 | | 3 | | 4 | | 5 | | 6 |
----- ----- ----- ----- ----- -----
So even though it is stored in a two dimensional array it is contagiously allocated memory during compilation. When you write a[1][1] the compiler accesses the (1*(no of columns) + 1 ) position from front i.e. the 4 position from start.
See http://www.fredosaurus.com/notes-cpp/arrayptr/23two-dim-array-memory-layout.html

i need a brief and simple understable advice to understand this code process

I am now learning the pointer and memory section of C. Now I am stuck on this code. I am not understanding how this code process and how the code shows result contestants[2] = 2. Please consider me as a very new learner and answer briefly how a single code worked and how's the result 2?
#include <stdio.h>
int main()
{
int contestants[] = {1, 2, 3};
int *choice = contestants;
contestants[0] = 2;
contestants[1] = contestants[2];
contestants[2] = *choice;
printf("I'm going to pick contestant number %i\n", contestants[2]); return 0;
}
int contestants[] = {1, 2, 3};
contestants is an array of integrs, indexed starting at 0, with values contestants[0] == 1, contestants[1] == 2 and `contestants[2] = 3.
int *choice = contestants;
choice is an integer pointer, assigned here to the address of the contestants array, which is the address of the first element of the contestants array. Therefore, *choice will give you the same result as contestants[0].
contestants[0] = 2;
This assigns 2 to contestants[0]. Now contestants[0] == 2 and, therefore, *choice == 2. The contestants array now looks like {2, 2, 3}.
contestants[1] = contestants[2];
Assigns the value 2 to contestants[1]. Now the contestants array looks like {2, 3, 3}.
contestants[2] = *choice;
Assigns *choice which is still the same as contestants[0] to contestants[2]. So the contestants array looks like {2, 3, 2}.
printf("I'm going to pick contestant number %i\n", contestants[2]); return 0;
Prints contestants[2], which is 2 as you observed.
contestants is an array of type integers which contains values {1, 2, 3}.
choice is a pointer of type int pointing to valid memory location of contestants.
Each element in array contestants are accessed as contestants[i], where i is index of array starting from 0. contestants[0] = 2; is what assigning value 2 to index location 0.
contestants[2] = *choice; - choice is a pointer, *choice is called dereferencing pointer to get the value pointing by pointer choice which is 2.
Typical memory layout is as follows,
contestants[]
choice 0 1 2
+-----+ +-------------------+
|0x100|------>| 1 | 2 | 3 |
| | | | | |
+-----+ +-------------------+
0x100 0x104 0x108

How does this recursive C code work?

There are lots of recursion questions and I basically understand some simple recursion algorithm such as sum of array elements. However, my friend gave me this code which reverses an array:
void r(int a[], int s)
{
if(s <=2 ) return;
int t = a[0];
a[0] = a[s-1];
a[s-1] = t;
r(&a[1], s-2); // this line confused me, why &a[1]
}
I know how to reverse an array using a normal for loop. But this code really confused me about recursion.
Can anyone explain the above line of code?
It is equvalent to
void r(int *arr, size_t len)
{
for ( ; len >= 2; arr+=1,len-=2 ) {
int t = arr[0];
arr[0] = arr[len-1];
arr[len-1] = t;
}
}
, where the recursive call is replaced by the loop. Ihe "increment" part of the loop (arr+=1,len-=2) is exactly the same as the parameters for the recursive call; the end condition (len >= 2) is equivalent to the recursion stopper (which was wrong in the original).
The idea behind this algorithm is at each step:
-: to swap the last a[s-1] and first a[0] elements of the array:
int t = a[0];
a[0] = a[s-1];
a[s-1] = t;
-: and to swap the middle recursively:
r(&a[1], s-2);
To understand the syntax, keep in mind that &a[n] is address of the n+1th element of the given array. If you have int *b = &a[1], then b[0] == a[1], b[1] == a[2], etc.
So:
&a[1] refers to an array starting at the second element of array a.
s - 2 means that the length of the array you pass recursively is shorter by 2 elements.
If you have an array [1 2 3 4 5 6 7 8 9 10], here's what happens as the recursion progresses:
[1 2 3 4 5 6 7 8 9 10] // r(&a[0], 10)
10 [2 3 4 5 6 7 8 9] 1 // r(&a[1], 8
10 9 [3 4 5 6 7 8] 2 1 // r(&(&a[1])[1], 6)
10 9 8 [4 5 6 7] 3 2 1 // r(&(&(&a[1])[1])[1], 4)
10 9 8 7 [5 6] 4 3 2 1 // r(&(&(&(&a[1])[1])[1])[1], 2)
Cool thing is that this analysis shows us that the terminating condtion s <= 2 is wrong: the innermost 2 elements in an even-sized array will never get swapped. It should be changed to s < 2.
Simplified Crazy walk trough;
void reverse(int a[], int s)
{
int temp; /* temporary value */
if (s <= 2) return; /* trigger done */
t = a[0]; /* temp = first index of a */
a[0] = a[s - 1]; /* a[0] = a[end - 1] (end including \0) */
a[s - 1] = t; /* a[end - 1] = temp */
r(&a[1], s - 2); /* pass address of a[1] and end - 2 */
}
Given the char array "ABCDEFG"
Simplified memory table could be:
Address Value
7 A
8 B
9 C
a D
b E
c F
d G
/* Or as used here: */
789abcd <- Simplified memory address
ABCDEFG
We get; main() calls reverse(ABCDEFG, 7)
List 1
Address ref. to A are pushed on to the stack (A{BCDEFG})
7 are pushed on to the stack
return address for caller is pushed onto the stack
etc.
function called
And something like
#::::::::::::::::::::::::::::::::::::::::::::::::::::
reverse(ABCDEFG, 7); # Push to STACK 0xB (As List 1)
#====================================================
789abcd <- Memory address.
ABCDEFG <- Values.
0123456 <- Indexes for a in recursion 1.
if (7 <= 2) return;
temp = A
+ .
a[0] = a[6] => ABCDEFG = GBCDEFG
+
a[6] = temp => GBCDEFG = GBCDEFA
reverse(BCDEFA, 5); # Push to STACK 0xC (As in List 1)
#====================================================
7 89abcd <- Memory addresses.
[G]BCDEFA <- Values
012345 <- Indexes for a in recursion 2.
if (5 <= 2) return;
temp = B
+ .
a[0] = a[4] => BCDEFA = FCDEFA
+
a[4] = temp => FCDEFA = FCDEBA
reverse(CDEBA, 3); # Push to STACK 0xD (As in List 1)
#====================================================
78 9abcd <- Memory addresses.
[GF]CDEBA <- Values.
01234 <- indexes for a in recursion 3.
if (3 <= 2) return;
temp = C
+ .
a[0] = a[2] => CDEBA = EDEBA
+
a[2] = temp => EDEBA = EDCBA
reverse(DCBA, 1); # Push to STACK 0xE (As in List 1)
#====================================================
789 abcd <- Memory addresses.
[GFE]DCBA <- Values.
0123 <- Indexes for a in recursion 4.
if (1 <= 2) return; YES!
#:::: roll back stack ::::
Pop STACK 0xE
Pop STACK 0xD
Pop STACK 0xC
Pop STACK 0xB
We are back in main() and memory region 789abcd has
been altered from ABCDEFG to GFEDCBA.
The important thing to realize is that a is a pointer to the first element of the array, so a is the same as &a[0]. &a[1] is a pointer to the second element of the array. So if you call the function with &a[1] as its argument, it works on the subarray that starts with the second element.
&a[1] is equivalent to a + 1, i.e. a pointer to the second element of the array. The function call reverses the "middle" s-2 elements of the array.
The function has to be called with:
A pointer to the first element of the array. In C it can be referenced by using the name of the array.
The size of the array.
The first 'if' checks that the array has as least two elements. Next, what the function does is to exchange the position of the first and the last element of the array.
The recursive call changes the bounds at which the next step has to work. It increments the beginning of the array by one position, and also decreases the end of the array by one position; since these two elements have been reversed in this iteration.

Resources