为什么这个数组中的最后两个值始终有效?

问题描述 投票:0回答:1

我正在用 C 语言编写堆栈来向朋友演示一些东西。我知道下面的函数返回指向垃圾内存的指针,因此我们不能依赖它们。这就是演示的重点。

#include <stdio.h>

int *oneToTen();
int *elevenToTwenty();

int main() {

  int *arr = oneToTen();

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

  elevenToTwenty();
  printf("\n\n\n");

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

  return 0;
}

int *oneToTen() {
  int arr[10];

  for (int i = 0; i < 10; ++i) {
    arr[i] = i + 1;
  }

  return arr;
}

int *elevenToTwenty() {
  int arr[10];

  for (int i = 0; i < 10; ++i) {
    arr[i] = i + 11;
  }

  return arr;
}

输出基本符合预期。我们得到垃圾内存,调用第二个函数会更改第一个函数返回的内存。

1
1
47405968
1
1833808032
1
-2092245084
-1687584767
9
10



43154832
1
47405968
1
1833808032
1
-2092245084
-1687584767
19
20

但是奇怪的事情发生了。每次我运行这个函数时,这个数组的最后两个元素永远不会被垃圾处理掉。所有其他数组元素都会变成垃圾,但最后两个元素不会。这是为什么?

我不太熟悉内存从堆栈中弹出后会发生什么,所以我真的不知道如何回答这个问题。我的猜测是,这可能与有 8 个值有关,所以它可能是 2 的幂?

编辑:我尝试更改数组中的元素数量,但最后两个元素始终保持不变

c memory callstack low-level
1个回答
0
投票

如果您在启用警告的情况下编译它,例如在 gcc 中,您将看到:

a.c: In function ‘oneToTen’:
a.c:31:10: warning: function returns address of local variable [-Wreturn-local-addr]
   31 |   return arr;
a.c: In function ‘elevenToTwenty’:
a.c:41:10: warning: function returns address of local variable [-Wreturn-local-addr]
   41 |   return arr;
      |          ^~~

从警告中,你就能找到问题所在。函数中的局部变量是自动变量,在函数退出时将被销毁。 使用指针和动态分配可以解决问题:

#include <stdio.h>
#include <stdlib.h>

#define SIZE 10

int *oneToTen() {
  int *arr = malloc(SIZE * sizeof (int));

  for (int i = 0; i < SIZE; ++i)
    arr[i] = i + 1;

  return arr;
}

int *elevenToTwenty() {
  int *arr = malloc(SIZE * sizeof (int));

  for (int i = 0; i < 10; ++i)
    arr[i] = i + 11;

  return arr;
}

int main() {
  int *arr = oneToTen();

  for (int i = 0; i < 10; ++i)
    printf("%d\n", arr[i]);
  free(arr);

  printf("\n\n\n");

  arr = elevenToTwenty();

  for (int i = 0; i < 10; ++i)
    printf("%d\n", arr[i]);
  free(arr);

  return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.