0

我在一本书中遇到了以下问题,并且我的系统结果始终为 "True" 。根据我的理解,原因是“int c”是由编译器优化的,因此 if() 语句没有效果,但我的印象是这会产生使用 c[a][b] 的错误消息因为 'c' 不是数组。

  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 }

谁能帮我澄清一下我的理解?

4

3 回答 3

4

该表达式x[y]等价于,*(x+y)因此无论您将其表述为 还是 都没有x[y]区别y[x]

事实上,"0123456789abcdef"[nybble % 0x10]也是一个有效的表达式,根据括号内的值返回其中一个字符。替代方案也是如此,如该程序所示:

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

打印b两次。所以,不,c根本不必是一个数组。

至于为什么它总是正确的,只需将它们转换为*(x+y)形式:

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

现在,因为a + *(b + c)在数学上与 完全相同*(c + b) + a,所以等式的两边都引用相同的内存位置,因此表达式将始终为真。


现在请记住,编译器可能足够聪明,可以发现它是同一件事并对其进行优化以始终为您提供真实的信息,但您仍然误入未定义的行为领域。

因为您没有显式设置c一个值,并且它不是静态存储持续时间,所以它将被赋予一个任意值。这意味着您实际上可能会b在实际数组末尾之外的数组中使用一个索引,这在 C 圈子中是一个很大的禁忌。

于 2013-09-18T06:19:58.930 回答
2

这是 C 语言的一个众所周知的怪癖

arr[10] 与 10[arr] 相同。

它背后的想法是 arr[10] 与 arr + 10 相同,并且 10 + arr 在数学上也应该意味着相同

于 2013-09-18T06:21:11.670 回答
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;
}

输出

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

打印的前两个数字表明b[i] == i[b]。这意味着将方括号外的数字作为数组索引*(i + b),其中 b 是数组起始位置的地址。将相同的想法扩展到i[b][c], *(i[b] + c)。因此,i[b][c]被评估为*(*(i + b) + c)

注意:在您的情况下,我真的相信该行为将是未定义的,因为c未初始化。

于 2013-09-18T06:24:14.973 回答