可能重复:
C语言中的负数组下标?
我能在数组中使用负索引吗?
#include <stdio.h>
int main(void)
{
char a[] = "pascual";
char *p = a;
p += 3;
printf("%c\n", p[-1]); /* -1 is valid here? */
return 0;
}
可能重复:
C语言中的负数组下标?
我能在数组中使用负索引吗?
#include <stdio.h>
int main(void)
{
char a[] = "pascual";
char *p = a;
p += 3;
printf("%c\n", p[-1]); /* -1 is valid here? */
return 0;
}
是的,在这种情况下-1
是有效的,因为它指向分配给你的char a[]
数组的内存中的一个有效位置。p[-1]
等同于*(p-1)
。在您的示例中遵循赋值链,它与a+3-1
或a+2
相同,这是有效的。
编辑:一般规则是,整数和指针(以及等效的指针索引操作)的加法/减法需要产生指向同一数组或数组末尾之后一个元素的结果才能有效。感谢Eric Postpischil提供了一个很好的注释。
p[-1]
等同于 p-1
应该读作 p[-1]
等同于 *(p-1)
。 - Robin Hsu强调是我的。因此,在您的特定示例中,6.5.6 加法运算符
8 ……如果表达式P
指向数组对象的第 i 个元素,则表达式(P)+N
(等效于N+(P)
)和(P)-N
(其中N
的值是 n)分别指向数组对象的第 i+n 个和第 i−n 个元素,前提是它们存在……
p[-1]
是有效的,因为它指向 a
的一个现有元素; 但是,a[-1]
将无效,因为 a[-1]
指向 a
的一个不存在的元素。同样,p[-4]
将无效,a[10]
也将无效,等等。当然是合法的。
(C99, 6.5.2p1) "其中一个表达式应具有“指向对象类型”的指针类型,另一个表达式应具有整数类型,结果的类型为“type”。
通常使用这样的负索引是一个不好的想法。然而,我发现有一个地方可以用到:三角函数查找表。对于这样的查找表,我们需要使用一些角度作为索引。例如,我可以使用度数作为索引来索引-180度到+180度之间的sin值。或者如果我想使用弧度,我可以使用PI的某个分数的倍数,比如PI/3,作为索引。然后我就可以通过PI/3的倍数获得-cos PI和cos PI之间的值。
是的,这是合法的,因为C语言允许您整天进行不安全的指针算术运算。但是,这很容易引起混淆,所以最好不要这样做。另请参见相同问题的答案。
p
不是数组,而是指向数组的指针。a
是一个数组,对于a
来说,负数索引总是无效的。 - Jim Balterint x = *(int*)NULL;
这段代码。您会认为这是有效的吗?您可以通过静态分析证明该代码导致未定义行为,因此我会说不是。 - Ed S.0
,但那是我的错误。我很快就编辑并将其替换为NULL
。再次强调,这取决于你如何定义“有效”。我认为大多数人会超越“程序是否编译通过?”这个层面,这是一个更有用的定义。 - Ed S.