为什么'c [& i]'编译而'c [i]'不编译?

时间:2016-10-18 21:39:19

标签: c arrays pointers syntax

此示例编译时没有警告/错误(gcc 4.8.2-Wall):

#include <stdio.h>
int main() 
{ 
    char c;
    int i;    
    printf("%p %02x\n",&i,c[&i]);
    printf("%p %02x\n",&c,c[&c]);

    // important to note that this line DOESN'T compile:
    //printf("%p %02x\n",&i,c[i]);
    //  which makes sense as c is NOT an array, it is a char.

    return 1;
}

为什么语法c [&amp; i]编译?是故意还是意外? 语法c [&amp; i]在语义上是否有效? (它有任何有用的含义吗?)

我的输出示例:(指针每次更改)

0xbfb2577c b7718cea
0xbfb2577b 08

这个问题起源于这里有一个奇怪的代码'ch2 [&amp; i]': C duplicate character,character by character

关于重复/类似问题的注释#0(经过反思更新): 这个问题不是关于c数组引用的链接问题的重复。它是相关的,因此引用它们很有用。相关问题讨论了有效的a [b]和b [a]情况,其中a或b中的一个是指针而另一个是int。这个问题涉及更奇怪的,也许应该是无效的情况,其中a或b中的一个是char。 对于C数组,为什么a [5] == 5 [a]? 14个答案 With arrays, why is it the case that a[5] == 5[a]? 字符串作为数组索引3答案 String as an array index

注意#1:编译器会发生这种情况,因为变量c的类型是char,当与指针结合使用时,它可以用作数组的索引。

注意#2:出于某种原因,c[<ptr>]的类型评估为<ptr>的类型。

例如:c[&pi]c[&pc]的结果类型导致以下代码中的警告:

int *pi; char *pc; pi=&i; pc=&c;
printf("%p %02x\n",&pi,c[&pi]);
printf("%p %02x\n",&pc,c[&pc]);

类型'int *'或'char *'而不是'unsigned int'的警告:

c/so_cweirdchar2.c: In function ‘main’:
c/so_cweirdchar2.c:13:5: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 3 has type ‘int *’ [-Wformat=]
     printf("pi %p %02x\n",&pi,c[&pi]);
     ^
c/so_cweirdchar2.c:14:5: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 3 has type ‘char *’ [-Wformat=]
     printf("pc %p %02x\n",&pc,c[&pc]);
     ^

2 个答案:

答案 0 :(得分:4)

在C中,[]后缀指针移位运算符是可交换的。如果a[i]是一个有效的表达式,那么i[a]也是如此,意味着同样的事情。虽然我们必须观察运营商的关联性和优先级,以确保我们正确地进行逆转。您的c[&i](&i)[c]的含义相同:指针&i被整数c取代。

[]的可交换性的基础是索引与指针位移和解除引用的组合之间的等价,其中+运算符是可交换的:

E1[E2]  <-->  *(E1 + E2)
  ^               ^
  |               |
  v               v
E2[E1]  <-->  *(E2 + E1)

在这里,我们理解E1是完全括号表达式,因此我们不关心优先级。实际上,我们正在操纵抽象语法树,其中E1E2是节点。

答案 1 :(得分:0)

编译时没有错误。完全有效的C:

int main (int argc, char** argv)
{
    int n=5;
    char *a="abcdefghijk";

    printf("%c\n", a[n]);
    printf("%c\n", n[a]);
    return 0;
}