# Thread: combined conditions in For loop

1. ## combined conditions in For loop

For the for loop below each outputs 4,3,2,1,0 - how does this work exactly?

the first loop:
for (p=a+4, i=0; i<=4; i++) PRD(p[-i]);

is this just that we start at p[4] and keep going down until i = 4 which leaves us at p[0]? can someone please walk me through how it is being interpreted?

the second loop:
for (p=a+4; p>=a; p--) PRD(a[p-a]);

the first pass of this look p = 4, a = 0? is output here "a[4-0,3-0,2-0,1-0,0-0]"?

Code:
```#define PRD(a) printf("%d", (a) )#define NL printf("\n");

// Create and initialse array
int a[]={0, 1, 2, 3, 4};

int main()
{
int i;
int* p;
for (p=a+4, i=0; i<=4; i++) PRD(p[-i]);
for (p=a+4; p>=a; p--) PRD(a[p-a]);
}```

2. This looks like a "test your knowledge of obscure, useless C constructs" exercise. It helps to know that a[i] is equivalent to *(a + i) and *(i + a) and i[a]. That is why you can do crazy things like "abcdef"[2] (which results in 'c'). Not that you should do that in real code.

Code:
`for (p=a+4, i=0; i<=4; i++) PRD(p[-i]);`
You're basically right on this.
That sets p to the address of a[4], and sets i to 0. Then it loops, continuing while i <=4. Each time, it calls the macro PRD, passing it p[-i] to print out, and incrementing i. Since p[-i] is equal to *(p + -i), and p = a+4, p[-i] can be seen as *(a + 4 - i), so it prints out values of *(a + 4 - 0), then *(a + 4 - 1), ..., *(a + 4 - 4). Or, a[4], a[3], ..., a[0].

Code:
`for (p=a+4; p>=a; p--) PRD(a[p-a]);`
You seem a little more confused on this one. It involves a bit more pointer arithmetic.
This also starts with p pointing to the address of a[4], however, it decrements p each time through the loop, continuing while p is >= a. Two little notes here. First, a (the name of the array) is interpreted as a pointer to the first element, i.e. a is equivalent to &a[0] or (a + 0). Second, when you add or subtract pointers, it is automatically scaled by the size of the thing pointed to. That is, if an int is 4 bytes, &a[1] - &a[0] is still only 1 (1 element apart) instead of 4 (4 bytes apart). So assuming a starts at some address like 0x1000, and ints are 4 bytes, you have

&a[0] = 0x1000
&a[1] = 0x1004
...
&a[4] = 0x1010

That means p starts at 0x1010 (and a is always &a[0] or 0x1000). So you print a[0x1010 - 0x1000] which is a[0x10] or a[16], but remember, it gets scaled down by the size of an int (4 bytes), so you end up with a[4]. Then p is decremented by 1 (subtracting sizeof(*p) or sizeof(int)), so next iteration p = 0x100c. Thus, you print a[0x100c - 0x1000] == a[12], scaled down gives a[3].

Hope that makes sense.

3. The first loop is doing just what you have posted, above. Remember that as you increase i, the index number for the array will go DOWN, instead of up, since i is being subtracted.

In the second loop, a is the address of the array's first element, so p-a is just a rather unintuitive way of writing [4-0], [3-0], [2-0], but using the pointer p, instead of an index number.

It's essential to know the relationship between a[number] and *(a+number), but in practice, the a[number] style is FAR more intuitive, and will result in FAR fewer errors.

4. p is a pointer to int.a is an array of int.So how does an array works(well pretty much)?You have a pointer(here the pointer of the array is a) and you say your system the offset you want and the pointer will go at the requested offset and give you access there.e.g. if i write a[3] then then the pointer a which located by default at the start of the array will move to the fourth cell(because we start counting from zero).
Also mind that a[3] is equivalent to *(a+3).
Code:
```a
|
|
V
+-----+-----+-------+-----+-----+
|data |data|data2|data|data|
+-----+-----+-------+-----+-----+```
so if i write *(a+2) the pointer will be transferred to data2
Code:
```#include <stdio.h>

int main(void) {
int a[]={0, 1, 2, 3, 4};

printf("%d\n",a[3]);
printf("%d\n",*(a+3));

return 0;
}```
So at your code line 11 sets pointer p to the fifth element of the array(because offset is +4 and we count from zero).So counter i is decreased in order to traverse the array in reverse.But because of the equivalent expressions i mentioned before p is now set back to the start of a.

Then in the second loop,we set pointer p again at the end of array a,because we move it four positions,starting from the zero.
Then p>=a means that the loop body is going to be executed as long as the pointer is at a cell which is in 'bigger' position(e.g. second element is at bigger position in comparisson with the first) or if the pointer p points where pointer a points.
Then it will make the pointer p point to a position with a smaller number(e.g from fifth cell to the fourth cell).

And when it says a[p-a] it means that p-a is resolved at an int .I run the program with this line
Code:
`for (p=a+4; p>=a; p--) printf("%d %d %d %d\n",a[p-a],p,a,p-a);`
output
Code:
```4 4202512 4202496 4
3 4202508 4202496 3
2 4202504 4202496 2
1 4202500 4202496 1
0 4202496 4202496 0```
the big numbers are addresses of course,because p and are pointers,so when writing *p we refer to where p points to ,but writing simple p we refer to it's own block of memory which contains it's address.
But if you do 4202512 - 4202496 you will find 16.Then p is decreased to point to a smaller position cell.So 4202508 - 4202496 =12 etc.
Notice that 4202496 remains as it was because a is not modified at all.
So why we find 16 but p-a gives as 4?
Why we find 12 but p-a gives as 3?
Well,in many systems int has size of 4.4 what?4 bytes .So every int is saved at a 4 bytes .An int is placed in an integer(you can imagine it as an array that holds the value of the number in binary).
So 4*4 requires 16 bits space to fit,3*4 12 bits to fit etc...

Edit->i am too slow,when starting writting no responses where here

5. Thank you very much. you explanations are very helpful. I understand much better now.

6. Originally Posted by anduril462
That is why you can do crazy things like "abcdef"[2] (which results in 'c').
Actually, that usage is obvious if you think about it. The index is inside the square brackets.

I would suggest it is crazier that 2["abcdef"] does the same thing (results in 'c'). Anyone who uses such a construct outside an obfuscated C context (almost) deserves to be summarily shot.