【问题标题】:Difference in printing out pointer value vs array打印出指针值与数组的区别
【发布时间】:2019-07-17 18:27:24
【问题描述】:

我有一个关于打印指针值和数组的问题。

int arr[5] = { 1, 2, 3, 4, 5 };
int * ptr = arr;

for (int i = 0; i < 5; i++) {
    (*ptr) += 2;
    ptr++;
    printf("%d", (*ptr));
}

上面是我先输入的,但没有用。所以我删除了 printf 行并输入了一个新代码,就是这个。它奏效了。

for (int i = 0; i < 5; i++) {
    printf("%d ", arr[i]);
}

我明白为什么第二个有效,但仍然不明白为什么第一个无效。

预期的输出是 3 4 5 6 7 但第一个代码的实际输出是 2 3 4 5 -858993460

【问题讨论】:

  • 您在错误的位置增加了 ptr。在 for 循环 (i++, ptr ++) 或 在 printf. 中增加它或者

标签: c


【解决方案1】:
int arr[5] = { 1, 2, 3, 4, 5 };
    int * ptr = arr;

    for (int i = 0; i < 5; i++) {
        (*ptr) += 2;
        ptr++;
        printf("%d", (*ptr));
    }

原因是你先增加指针然后打印它的内容。

也许您需要先打印内容,然后将其递增以指向下一个元素。

int arr[5] = { 1, 2, 3, 4, 5 };
    int * ptr = arr;

    for (int i = 0; i < 5; i++) {
        (*ptr) += 2;
        printf("%d", (*ptr));
        ptr++;
    }

【讨论】:

    【解决方案2】:

    错误的原因是您在打印当前值(您实际想要打印的值)之前使 ptr 指向下一个值。 让我们逐行考虑 for 循环的第一步,并记住,一开始您将 ptr 指向数组的第一个元素(int * ptr = arr;):

    1. (*ptr) += 2; - 这一行等价于 (*ptr) = (*ptr) + 2;这意味着“将ptr指向的内存地址中的值增加2”,所以现在数组的第一个元素是3(ptr不变,它指向数组的第一个元素)。
    2. ptr++; - 这一行增加了 ptr,或者换句话说 ptr 现在将指向下一个内存位置,在你的情况下是数组的第二个元素。第一个元素为 3,第二个元素的值不变。
    3. printf("%d", (*ptr)); - 此行打印存储在 ptr 指向的内存位置中的值,但是您使 ptr 指向上一行中的下一个位置,因此 ptr 指向,正如我之前所说的,指向第二个元素。

    我希望您了解在 for 循环的后续步骤中会发生什么。

    【讨论】:

      【解决方案3】:

      它不起作用的原因是你在打印出来之前增加了指针。

      for (int i = 0; i < 5; i++) {
          (*ptr) += 2;
          /* ptr++; */
          printf("%d", *ptr++);
      /*                   ^^ increment after */
      }
      

      【讨论】:

        【解决方案4】:

        正如这里的人所说,你的输出是错误的,因为你在打印它的内容之前增加了 ptr。

        你得到像“-858993460”这样的值的原因是

        ptr = arr 将 ptr 设置为数组内存位置。它的工作方式是,arr 有一个特定的内存位置,并保留该内存位置以及它后面的所有内存位置,直到 memorylocation+(length-1)。

        所以假设 arr 位于“15007140”位置。

        然后将每个内存位置的值设置如下:

        15007140 = 1
        15007144 = 2
        15007148 = 3
        15007152 = 4
        15007156 = 5
        

        执行ptr=arr 实质上设置ptr=15007140。调用 (*ptr) 时,您可以访问内存位置 15007140 中的值。执行 ptr++ 会将 15007140 增加到 15007144。如果调用 (*ptr),您可以访问该位置中的值,在这种情况下为 2。

        如果你越来越多地增加 ptr,你实际上可以将它增加到超过 15007156(这是数组的末尾),从而可以访问内存地址及其值,它们不是代码的直接部分(如你所见在您的情况下使用 -858993460)。

        因为 ptr 从第一个数组位置的地址开始,所以在打印之前执行ptr++;,最终会先打印数组位置 arr[1] 的值,最后打印“arr[6]”(但是因为您的数组的长度只有 5,“arr[6]”实际上是与你的内存中的数组无关的东西)

        “正确”的代码是:

        for (int i = 0; i < 5; i++) {
            (*ptr) += 2;
            printf("%d\r\n", ptr);
            ptr++;
        }
        

        【讨论】:

          【解决方案5】:

          在第一个代码中: (*ptr) += 2; 将 'ptr' 指向的值增加 2 。

          ptr++; 它将指针按位置 1 递增,这意味着它指向下一个元素。在循环结束时,它指向具有垃圾值的 arr[5]。

          【讨论】:

          • has a garbage value - 你怎么知道的?访问 arr[5] 是未定义的行为,您不应假设此类访问会发生什么。
          【解决方案6】:

          如果您已经在使用 for 循环。 将 ptr++ 替换为 ptr+i。

          int arr[5] = { 1, 2, 3, 4, 5 };
          int * ptr = arr;
          
          for (int i = 0; i < 5; i++) {
              *(ptr + i) += 2;
              printf("%d", *(ptr + i));
          }
          

          【讨论】:

          • ptr+i; ? prt+i 是做什么的?它只是将i 添加到ptr 并丢弃结果?
          • *(Ptr + i) = ptr[ i ]
          • 代码仍然错误,不会产生 OP 正在寻找的预期输出
          • 看起来很简单,但又很复杂:D
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-09-22
          • 1970-01-01
          • 2017-10-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-03
          • 1970-01-01
          相关资源
          最近更新 更多