重新初始化C语言的指针

时间:2016-06-21 12:11:17

标签: c arrays pointers

我目前正在通过Dan Gookin的书“Beginning C Programming for Dummies”学习C编程。

我目前正在阅读的一个主题是数组实际上是指针。 Dan试图通过以下代码证明:

#include <stdio.h>

int main()
{
    int numbers[10];
    int x;
    int *pn;

    pn = numbers;       /* initialize pointer */

/* Fill array */
    for(x=0;x<10;x++)
    {
        *pn=x+1;
        pn++;
    }

    pn = numbers;

/* Display array */
    for(x=0;x<10;x++)
    {
        printf("numbers[%d] = %d, address %p\n",
                x+1,*pn,pn);
        pn++;
    }

    return(0);
}

我的问题实际上是第17行。我意识到如果我没有像第17行那样再次重新指向指针,那么在第二个pn循环序列中显示的指针for的查看值是一堆没有意义的垃圾。因此,我想知道为什么需要再次重新指针pn以使代码按预期工作?

7 个答案:

答案 0 :(得分:3)

数组不是指针,但C允许您将数组分配给数组变量类型的指针,其效果是该指针将指向数组中的第一项。这是pn = numbers的作用。

pn是指向int的指针,而不是指向数组的指针。它指向一个整数。增加指针时,它只会切换到下一个内存位置。它所做的移动是指针类型的大小,因此在这种情况下为int

那么这证明了什么?并不是说数组是一个指针,而只是一个数组是一个连续的内存块,它的数量是数组项类型的N倍。

当你运行第二个循环时,你的指针到达了一块不再属于数组的内存,所以你得到了垃圾&#39;这只是该地点恰好存在的信息。

如果要通过递增指针再次遍历数组,则必须将该指针重新初始化为第一个项目。 for循环只执行一项操作,即计数为10.它不知道数组并且它不知道指针,因此循环不会自动重置指针给你。

答案 1 :(得分:2)

由于pn在第一个循环中递增,因此在第一个循环结束后,pn将指向numbers数组之外的地址。因此,您必须在第二个循环之前将pn初始化为数组的开头,因为您使用相同的指针来打印内容。

答案 2 :(得分:1)

因为您在以下代码段中更改了pn语句中pn++中包含的地址。

for(x=0;x<10;x++)
    {
        *pn=x+1;
        pn++;
    }

答案 3 :(得分:1)

pn指针用于指向numbers数组。

第一个for - 循环使用pn设置值,逐个元素地逐步执行pn。在循环结束后,pn指向numbers的末尾(在未分配的第11个元素处)。

要使第二个for - 循环起作用,即通过单步执行pn再次循环numbers,需要将pn移动到numbers数组的前面,否则你将访问你不应该看的内存(未分配的内存)。

答案 4 :(得分:1)

第一个数组是不是指针。当它们在函数调用中使用时,它们衰减指针,并且可以(几乎)使用它们。

一些微妙的差异

int a[5];      /* array */
int *pa = a;   /* pointer */

pa[0] = 5;
printf("%d\n", a[0]);   /* ok it is the same here */
printf("address of array %p - address of pointer %p, value of pointer\n",
    &a, &pa, pa); /* &a is the same as pa not &pa */
printf("size of array %d - size of pointer %d\n", sizeof(a), sizeof(pa));

sizeof(a)在这里5 * sizeof(int)sizeof(pa)是指针的大小。

现在提问:

首次循环后,pn指向p[10],不再指向p[0]。这就是你必须重置它的原因。

答案 5 :(得分:1)

只是为了让点回家,数组不是指针。当您将numbers声明为int numbers[10]时,您会在内存中获得以下内容:

         +---+
numbers: |   | numbers[0] 
         +---+
         |   | numbers[1]
         +---+
          ...
         +---+
         |   | numbers[9]
         +---+

没有存储空间用于指向numbers的第一个元素的单独指针。当表达式numbers出现在任何地方,并且不是 sizeof或一元&运算符的操作数时,它会被转换(“衰减“)到”指向int的指针“类型的表达式,表达式的值是数组的第一个元素的地址。

您使用pn做的是将其设置为指向numbers的第一个元素,然后“遍历”数组:

         +---+ 
numbers: |   | <------+ 
         +---+        |
         |   |        |
         +---+        |
          ...         |
         +---+        |
         |   |        |
         +---+        |
          ...         |
                      |
         +---+        |
     pn: |   | -------+ 
         +---+

表达式pn++使pn前进到指向下一个整数对象,在本例中是数组的下一个元素:

         +---+ 
numbers: |   | 
         +---+ 
         |   | <------+
         +---+        |
          ...         |
         +---+        |
         |   |        |
         +---+        |
          ...         |
                      |
         +---+        |
     pn: |   | -------+ 
         +---+

每个pn++使指针前进,直到第一个循环结束时,您有以下内容:

         +---+ 
numbers: |   | 
         +---+ 
         |   | 
         +---+ 
          ...  
         +---+ 
         |   | 
         +---+ 
          ...  <------+
                      |
         +---+        |
     pn: |   | -------+ 
         +---+

此时,pn指向紧跟在数组末尾之后的对象。这就是你必须在下一个循环之前重置pn的原因;否则你在numbers之后立即遍历内存,它可以包含几乎任何东西,包括陷阱表示(即,与给定类型的合法值不对应的位模式)。

尝试访问超过数组末尾的内存超过一个内存会调用未定义的行为,这可能意味着从您的代码直接崩溃到显示垃圾到按预期工作。

答案 6 :(得分:0)

在填充数组期间,指针pn递增,数据放在数组上。用于打印数组内容的相同指针变量。因为这种重新初始化已经完成。