C *当x是指向未定义维度数组的指针时,x与x[0]不同

C *当x是指向未定义维度数组的指针时,x与x[0]不同,c,language-lawyer,C,Language Lawyer,我认为a[0]相当于*a,但后来我遇到了这段代码: int arr[] = {1, 2, 3}; int (* a)[] = &arr; printf("%d", (*a)[2]); // compiles printf("%d", a[0][2]); // errors out 有一个指向未指定大小的数组的指针。第一个表达式编译得很好,而第二个表达式的结果是 test.c:8:21: error: invalid use of array with unspecified bound

我认为a[0]相当于*a,但后来我遇到了这段代码:

int arr[] = {1, 2, 3};
int (* a)[] = &arr;
printf("%d", (*a)[2]); // compiles
printf("%d", a[0][2]); // errors out
有一个指向未指定大小的数组的指针。第一个表达式编译得很好,而第二个表达式的结果是

test.c:8:21: error: invalid use of array with unspecified bounds
     printf("%d", a[0][2]);
                     ^
叮当声的错误是

error: subscript of pointer to incomplete type 'int []'
和来自MSVC v19.10

error C2036: 'int (*)[0]': unknown size

为什么[0]不等同于*a?

这两个值不是严格等价的。[0]完全等同于*a+0

比如说

一元*运算符的操作数应为指针类型。 哪个int*[]是;解引用*a的结果是int[],它衰减为int*,然后用[2]索引,结果是3

然而,a[0][2]相当于*a+0[2],这里首先应用二进制+运算符的规则!说

约束条件

此外,两个操作数都应具有算术类型,或者一个操作数应为指向完整对象类型的指针,另一个操作数应具有整数类型。递增等于加1。 0具有整数类型,a是指针,但它不是指向完整对象类型的指针,这意味着它与约束不匹配


由于此文本出现在约束部分,一致性编译器必须将其诊断为约束冲突。一如往常,一致性实现仍然可以正确地翻译无效程序,但至少GCC似乎会以错误消息彻底拒绝这一点。

这两种方法并非严格等效。[0]完全等同于*a+0

比如说

一元*运算符的操作数应为指针类型。 哪个int*[]是;解引用*a的结果是int[],它衰减为int*,然后用[2]索引,结果是3

然而,a[0][2]相当于*a+0[2],这里首先应用二进制+运算符的规则!说

约束条件

此外,两个操作数都应具有算术类型,或者一个操作数应为指向完整对象类型的指针,另一个操作数应具有整数类型。递增等于加1。 0具有整数类型,a是指针,但它不是指向完整对象类型的指针,这意味着它与约束不匹配


由于此文本出现在约束部分,一致性编译器必须将其诊断为约束冲突。和往常一样,一致性实现仍然可以正确地翻译无效程序,但至少GCC似乎会以错误消息拒绝此操作。

简短回答:函数指针不能用于指针算术。@iBug是的,我也要添加它,但它不在这一点上。@iBug true,但这是一个怎样的答案呢?简短的回答:函数指针不能用于指针算术。@iBug是的,我也打算添加它,但它不是重点。@iBug是真的,但这是一个怎样的答案呢?在这里,我发现了一个错误,让MSVC中的任何人都知道。显然,msvc认为int*[]是int*[0]…@AnttiHaapala,这是从第一个索引中获取的吗?@SouravGhosh D'oh,它是一个副本:F-我以为我已经进行了彻底的搜索,但除了搜索有关msvc bug的讨论外,找不到副本。所以我想这很好。出于好奇,为什么你不删除你的问题,就像你删除其他OP写的问题一样,因为你的问题是重复的呢?而在这里,我发现了一个bug,在MSVC中可以看到任何人。显然,msvc认为int*[]是int*[0]…@AnttiHaapala,这是从第一个索引中获取的吗?@SouravGhosh D'oh,它是一个副本:F-我以为我已经进行了彻底的搜索,但除了搜索有关msvc bug的讨论外,找不到副本。所以我想这很好。出于好奇,为什么你不删除你的问题,就像删除其他OP写的问题一样?