0

I came across the below problem in a book and on my system result is always "True" . As per my understanding, the reason for this is "int c" is optimized by compiler, hence the if() statement has no effect but i was under the impression that this would generate a error message for using c[a][b] as 'c' is not an array.

  1 #include<stdio.h>
  2 
  3 int main()
  4 {
  5         int a[2] = {0,0};
  6         int b[1] = {0};
  7         int c;
  8         getchar();
  9         if(a[b[c]] == c[b][a])
 10                 printf("True");
 11         else    
 12                 printf("False");
 13 }

Can anyone please help me clear my understanding?

pkumarn
  • 1,383
  • 4
  • 22
  • 29

3 Answers3

4

The expression x[y] is equivalent to *(x+y) hence it makes no difference whether you state it as x[y] or y[x].

In fact, "0123456789abcdef"[nybble % 0x10] is also a valid expression, returning one of those characters depending on the value within the brackets. So is the alternative, as shown in this program:

#include <stdio.h>
int main() {
    char *arr = "0123456789abcdef";
    int nybble = 11;
    printf ("%c%c\n", arr[11], 11[arr]);
    return 0;
}

which prints b twice. So, no, c doesn't have to be an array at all.

In terms of why it's always true, just convert them to the *(x+y) form:

   a[b[c]]         == c[b][a]
=> a[*(b + c)]     == (*(c + b))[a])
=> *(a + *(b + c)) == *(*(c + b) + a)

Now, because a + *(b + c) is mathematically exactly the same as *(c + b) + a, both sides of the equation reference the same memory location, hence the expression will always be true.


Now keep in mind that the compiler may be smart enough to figure out that it's the same thing and optimise it to always give you true, but you're still straying into undefined behaviour territory.

Because you don't explicitly set c to a value, and it's not of static storage duration, it will be given an arbitrary value. That means that you may actually use an idex into the b array that's beyond the end of the actual array, a big no-no in C circles.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 1
    But remember: The standard forbids to access an array declared as `arr[5][5]` by `arr[6][0]` as the standard says, you are not allowed to break out of the array boundaries which are 5 and 5 (or as index 4 and 4) in my example ;) – dhein Sep 18 '13 at 06:35
  • @Zaibis, you caught me mid-edit, I've explained why it's a bad idea and undefined behaviour. – paxdiablo Sep 18 '13 at 06:37
2

This is a well known quirck of the C language

arr[10] is the same as 10[arr].

The idea behind it is that arr[10] is the same as arr + 10 and 10 + arr should also mean the same mathematically

Serve Laurijssen
  • 9,266
  • 5
  • 45
  • 98
0
# include <stdio.h>

int main(int argc, char const *argv[])
{
  int a = 0, b[10], c[10], i = 0;
  for (; i < 10; i++)
  {
    b[i] = c[i] = i;
    printf ("%d\t%d\t%d\n", b[i], i[b], i[b][c]);
  }
  return 0;
}

Output

0   0   0
1   1   1
2   2   2
3   3   3
4   4   4
5   5   5
6   6   6
7   7   7
8   8   8
9   9   9

The first two numbers printed show that b[i] == i[b]. It means that the number outside the square brackets is taken as the array index *(i + b) where b is the address of the array's starting location. Extending the same idea to i[b][c], *(i[b] + c). So, i[b][c] is evaluated as *(*(i + b) + c).

NOTE: In your case, I really believe that the behaviour would be undefined as c is not initialized.

thefourtheye
  • 233,700
  • 52
  • 457
  • 497