【问题标题】:Using negative number as array index使用负数作为数组索引
【发布时间】:2014-08-29 18:33:46
【问题描述】:

我遇到了一个竞争性问题,询问以下输出:

#include <stdio.h>
int main()
{
    int a[] = {0,1,2,3,4};
    int i, *ptr;
    for(ptr = a+4, i=0; i <=4; i++)
    printf("%d", ptr[-i]);
    return 0;
}

我确实读过这个主题:Are negative array indexes allowed in C? 但是我不清楚 -ve 符号如何以相反的顺序生成数组,即。 4, 3, 2, 1, 0

【问题讨论】:

  • 根据您问题的标题,您没有使用负数作为 array 索引;您正在使用指针ptr 和索引-i 来计算a[] 中某个元素的指针算术。数组a[] 始终以0 为根,对于一些小于零的n,通过a[n] 取消对it 的引用是未定义的行为。数组不是指针。下面的潮水般的答案很好地解释了指针数学概念。
  • a[b] == *(a + b) == b[a]
  • 从上面记住 WhozCraig 的回答。在您的职业生涯中,您可能会遇到使用此类指针在“字节”数组中“戳”和“删除”值的代码。这有时甚至用于敲入空值以终止字符串?上面的问题是“pythonesque”,因为否定可以在 Python 中使用?

标签: c arrays pointers


【解决方案1】:

首先,请记住,在 C 中,表达式 ptr[index]*(ptr+index) 的含义相同。

现在让我们再看看你的表达式:ptr 在循环之前设置为a+4;然后您将-i 索引应用于它。因此,等价的指针算术表达式如下:

printf("%d", *(a+4-i));

这个表达式向后迭代数组,产生你看到的结果。

【讨论】:

  • 简单优雅的解释!
【解决方案2】:

之所以起作用,是因为 [] 运算符进行了指针相加。

当你引用时

a[x]

实际发生的是它获取 a 的内存地址并添加 sizeof(int)*x

所以如果你将 ptr 设置为 a+4,你将是 a+sizeof(int)*4

然后,当你输入一个负值时,你会向后移动内存地址。

【讨论】:

    【解决方案3】:

    ptr[-i] 衰减为 *(ptr + (-i))。在第一次迭代中,当i = 0 时,ptr[-i] 访问了a 数组的最后一个元素,因为最初ptr 被设置为等于a + 4,这意味着 - 取a 开头的地址并添加4 * sizeof(int) (因为 ptr 的大小为 int)。在每次下一次迭代中,当 i 递增时,会访问数组的前一个元素。

    【讨论】:

    • 严格来说,表达式一不会“衰减”成表达式二:它们只是等价的表达式。如果你写 *(a + (-i)) 尽管 OP 将 a 定义为数组,a 确实会衰减为指向 a 的第一个元素的指针。
    【解决方案4】:

    in 是 for 语句

    for(ptr = a+4, i=0; i <=4; i++)
    

    指针ptr设置为a+4也可以通过以下方式完成

    ptr = &a[4];
    

    如果你用托盘输出指针所指向的值为例

    printf( "%d\n", *ptr );
    

    你会得到4。也就是指向数组最后一个元素的指针。

    在循环内部使用了表达式 ptr[-i] 。对于 i 等于 0,它等效于 ptr[0] 或简单地等于 *ptr,即将输出数组的最后一个元素。 对于 i 等于 1 表达式 ptr[-i] 等价于 a[4 - 1] 或简单的 a[3]。当表达式 ptr[-i] 等于 a[4 - i] 时等于 2 时 a[4 - 2] 又是 a[2] 等等。 所以你会得到

    4321
    

    【讨论】:

      【解决方案5】:

      a+4 给出了一个指向a 的第五个元素的指针。所以ptr 指的是那个位置。

      然后循环将 i 从 0 计数到(包括)4。

      取消引用ptr[-i] 等效于*(ptr - i)(根据定义)。因此,由于i 为 0 且ptra+4,它等价于a+4-0,然后是a+4-1,然后是a+4-2,以此类推直到a+4-4,这(显然足够)等于a.

      【讨论】:

        【解决方案6】:

        正如我在 C/C++ 中的评论中提到的那样

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

        对于你的情况,所有这些都很好

        printf("%d", *(a + 4 - i));
        printf("%d", a[4 - i]);
        printf("%d", 4[a - i]);
        ...
        

        【讨论】:

          猜你喜欢
          • 2021-12-25
          • 1970-01-01
          • 2011-04-29
          • 1970-01-01
          • 2018-07-13
          • 1970-01-01
          • 2014-01-21
          • 2018-04-27
          • 2019-06-02
          相关资源
          最近更新 更多