数组中的负数索引

5

可能重复:
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;
}

3
p不是数组,而是指向数组的指针。a是一个数组,对于a来说,负数索引总是无效的。 - Jim Balter
1
“is valid”指的是“能够编译通过”吗?我认为这里大多数人将“is valid”解释为“能够编译且运行结果可预测且可重复”。 - Code-Apprentice
1
@willglynn:同意Jim和Code-Guru的观点。您也可以编译 int x = *(int*)NULL; 这段代码。您会认为这是有效的吗?您可以通过静态分析证明该代码导致未定义行为,因此我会说不是。 - Ed S.
1
@willglynn:“未定义”并不意味着“实现相关”,而是意味着“未定义”,也就是说,从来没有定义过。“未指定”意味着“实现相关”。标准在正确的时间使用正确的术语,而不是随机选择这两个术语之一。 - Ed S.
1
@willglynn:嗯,不,从来不可以解引用空指针。永远不行。我一开始写的是0,但那是我的错误。我很快就编辑并将其替换为NULL。再次强调,这取决于你如何定义“有效”。我认为大多数人会超越“程序是否编译通过?”这个层面,这是一个更有用的定义。 - Ed S.
显示剩余6条评论
5个回答

8

是的,在这种情况下-1是有效的,因为它指向分配给你的char a[]数组的内存中的一个有效位置。p[-1]等同于*(p-1)。在您的示例中遵循赋值链,它与a+3-1a+2相同,这是有效的。

编辑:一般规则是,整数和指针(以及等效的指针索引操作)的加法/减法需要产生指向同一数组或数组末尾之后一个元素的结果才能有效。感谢Eric Postpischil提供了一个很好的注释。


@EricPostpischil 感谢您的评论,我编辑了答案以使其更加精确。 - Sergey Kalinichenko
我认为这是一个笔误:p[-1] 等同于 p-1 应该读作 p[-1] 等同于 *(p-1) - Robin Hsu

3

C 2011在线草案

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] 也将无效,等等。

2

当然是合法的。

(C99, 6.5.2p1) "其中一个表达式应具有“指向对象类型”的指针类型,另一个表达式应具有整数类型,结果的类型为“type”。


你可以使用负数数组索引,因为C语言允许您使用带有数组下标运算符的负整数。在我看来,这是真正的原因,当然还有与指针算术相关的限制以及如果您解除引用指针,则与间接操作符相关的限制。 - ouah

1

通常使用这样的负索引是一个不好的想法。然而,我发现有一个地方可以用到:三角函数查找表。对于这样的查找表,我们需要使用一些角度作为索引。例如,我可以使用度数作为索引来索引-180度到+180度之间的sin值。或者如果我想使用弧度,我可以使用PI的某个分数的倍数,比如PI/3,作为索引。然后我就可以通过PI/3的倍数获得-cos PI和cos PI之间的值。


-2

是的,这是合法的,因为C语言允许您整天进行不安全的指针算术运算。但是,这很容易引起混淆,所以最好不要这样做。另请参见相同问题的答案


3
既不危险也不令人困惑。 - Jim Balter
不在示例代码中,所以它是可以证明安全的,并且足够接近定义,不会引起混淆。(另外,我的陈述是C允许不安全的算术运算,而不是这是一个例子。)话虽如此,我认为在你将操作分解到各种函数中并在几年后交给维护编码人员之后,你可能会遇到麻烦,我认为最好保留原始数组指针并使用正偏移量。 - willglynn
不得不同意JimBalter先生的观点。有时我也会这样做,虽然不是字面上的负索引,而是通过指针根据位置进行复杂数据搜索,甚至通过代理来实现辅助功能。 - Morpfh
此外,我的观点是C语言允许不安全的算术运算,而不是这个例子一定不安全。你说“不要这样做”这是一个笼统的谴责。 - Jim Balter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接