【问题标题】:Letting the user define size of an array让用户定义数组的大小
【发布时间】:2018-11-29 06:54:28
【问题描述】:

如何让用户选择一个数字,比如 n,然后创建一个大小为 n 的数组?

我可以说int a[]=malloc (n*sizeof(int))吗?

【问题讨论】:

  • 我会小心让用户分配任意大小的数组。除非他们被信任,即你。巨大的分配可能存在稳定性问题

标签: c arrays malloc


【解决方案1】:

有两种方法可以做到这一点。如果数组很小,那么你可以使用变长数组

/* Valid in C99 and later */
int n;
scanf("%d", &n);
int a[n];  

这将在堆栈上分配内存。另一种方法是您可以使用动态内存分配,它将在堆上分配内存

 int *a = malloc(n*sizeof(int));  

【讨论】:

  • 你认为小数组大小是多少?
  • @fbynite;因为通常堆栈的大小是有限的,VLA 的内存是在堆栈上分配的。
  • 是的,这就是我想知道的大小。你说的大小边界是多少,这个数组可能超过 X 个字节,应该在堆上分配?
  • VLA 自 C99 起为 C,自 C11 起为可选。在 C++ 中它们根本不存在。
  • 是的,当然。我的评论不是批评,只是补充。
【解决方案2】:

你的想法几乎是正确的:

int a[] = malloc(n*sizeof(int));

使用malloc 是正确的方法。 但是您不能将返回的地址分配给数组。

您必须改用指针变量:

int *a = malloc(n*sizeof(int));

【讨论】:

    【解决方案3】:

    是的,如果你想在运行时设置数组的大小。

    那么你应该去动态内存分配(malloc/calloc)。

    int a[]=malloc (n*sizeof(int));//this not possible.
    int *a =malloc (n*sizeof(int)); // this is possible.
    

    【讨论】:

      【解决方案4】:

      分配内存以创建数组有两种基本方法,其中数组的大小被确定为输入:

      第一个是, 在内存的“堆栈”段中为数组分配内存,其中数组的大小作为输入ant,然后定义该特定大小的数组并相应地授予内存。

      int n;
      scanf("%d",&n);            //scanning the size
      int arr[n];                //declaring the array of that particular size here
      

      第二个是, 在内存的“堆”段中分配所需的内存。它是在运行时分配的内存(程序的执行) 因此,另一种声明大小由用户定义的数组的方法是

      int n,*arr;
      scanf("%d",&n);
      arr=malloc(n*sizeof(int));        //malloc function provides a contiguous space 
      

      arr=calloc(n,sizeof(int));      //calloc function is similar,initializes as 0
      

      要使用这两个函数,请确保包含 stdlib.h。

      【讨论】:

      • 无需在 C 中投射 void-pointers。只需删除那些 (int*)
      • VLA 自 C99 起为 C,自 C11 起为可选。在 C++ 中它们根本不存在。
      【解决方案5】:

      可变长度数组 (VLA) 在 C99 中添加到 C 中,但在 C11 中变为可选。不过,它们仍然得到广泛支持。这是在运行时定义具有用户选择大小的数组的最简单方法。

      除了 VLA 可能并非在所有平台上都可用之外,它们还可能在分配失败时静默失败。这是malloc()在正确使用时避免的缺点。

      您不能在 C 中分配给数组,而是需要将 malloc() 返回的值存储在指针中。请注意,当分配失败时,malloc() 返回NULL,允许代码检查失败并相应地继续。实际分配可能如下所示:

      int *a_dyn = malloc(sizeof *a_dyn * arr_sz);
      

      这是调用malloc() 的惯用方式。请注意有no need to cast the result of malloc(),并注意sizeof 的操作数不是显式类型,而是涉及a_dyn 的表达式。 sizeof 运算符使用表达式*a_dyntype,它实际上是int(没有取消引用)。与使用显式类型进行编码相比,在程序生命周期中类型发生变化时,这更不容易出错并且更容易维护。还要注意sizeof 表达式出现在arr_sz 之前。这是一个很好的做法:有时您可能会遇到这样的电话:

      int *arr = malloc(sizeof *arr * nrows * ncols);
      

      首先放置sizeof 会强制使用size_t 值完成乘法,有助于避免乘法中的溢出问题。

      不要忘记在不再需要时释放使用malloc() 分配的任何内存,避免内存泄漏。

      无论您使用 VLA 还是 malloc(),您都必须在使用前验证用户输入以避免未定义的行为。尝试分配非正数大小的数组会导致未定义的行为,而尝试分配过多内存将导致分配失败。

      下面是一个示例程序,说明了所有这些:

      #include <stdio.h>
      #include <stdlib.h>
      
      #define ARR_MAX  1024                 // some sensible maximum array size
      
      int main(void)
      {
          int arr_sz;
          int ret_val;
          /* validate user input */
          do {
              printf("Enter array size: ");
              ret_val = scanf("%d", &arr_sz);
          } while (ret_val != 1 || arr_sz < 1 || arr_sz > ARR_MAX);
      
          /* use a VLA */
          int a_vla[arr_sz];
          for (int i = 0; i < arr_sz; i++) {
              a_vla[i] = i;
              printf("%d ", a_vla[i]);
          }
          putchar('\n');
      
          /* use malloc() */
          int *a_dyn = malloc(sizeof *a_dyn * arr_sz);
          if (a_dyn == NULL) {                                 // malloc failure?
              fprintf(stderr, "Unable to allocate memory\n");
          } else {                                             // malloc success
              for (int i = 0; i < arr_sz; i++) {
                  a_dyn[i] = i;
                  printf("%d ", a_dyn[i]);
              }
              putchar('\n');
          }
      
          /* avoid memory leaks */
          free(a_dyn);
      
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 2018-02-09
        • 2013-12-22
        • 1970-01-01
        • 1970-01-01
        • 2015-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多