【问题标题】:Defining Array C/C++定义数组 C/C++
【发布时间】:2013-12-08 08:37:12
【问题描述】:

这两种数组定义有什么区别,哪一种更正确,为什么?

#include <stdio.h>
#define SIZE 20

int main() {

    // definition method 1:
    int a[SIZE];
    // end definition method 1.

    // defintion method 2:
    int n;
    scanf("%d", &n);
    int b[n];
    // end definition method 2.

    return 0;
}

我知道如果我们从stdin 读取大小变量n,将我们的(我们将使用的内存块)数组定义为指针并使用stdlib.harray = malloc(n * sizeof(int)) 会更正确,而不是将其标记为int array[n],但又是为什么呢?

【问题讨论】:

  • 以下答案中未提及的不同之处当然是,方法 1 仅在您知道在设计时(即在编写程序时)最终用户有多少项目时才有效将需要。曾经。使用动态数组,最终用户可以拥有任意数量的项目。

标签: c++ c arrays c-preprocessor


【解决方案1】:

这不是“更正确”或“更不正确”。它要么 x要么正确。特别是,这在 C 中有效,但在 C++ 中无效。

【讨论】:

  • 好的,但是在 C 中使用哪一个是正确的?还是在这种情况下没关系?
  • @DragosRizescu 如果您只在本地使用数组,那么没有理由使用malloc(),所以我更喜欢 VLA 方法。如果你确实需要从函数中返回它,那么你不能使用本地数组,因为它在返回时被破坏,所以你需要malloc()
【解决方案2】:

您正在声明动态数组。将动态数组声明为

的更好方法
int *arr;  // int * type is just for simplicity
arr = malloc(n*sizeof(int*));  

这是因为可变长度数组只允许在 C99 中使用,而您不能在 c89/90 中使用它。

【讨论】:

  • 但在 C++ 中,您也不会真正使用 malloc()std::vector,或至多new[]。此外,在这种特殊情况下,我认为没有理由使用 malloc() ——该变量仅在函数内部本地使用。
  • @H2CO3;感谢您在 C++ 中纠正我关于 malloc 的问题。但是 VLA 只允许在 C99 中使用,这就是为什么我认为 malloc 更好。
  • 我想知道为什么人们在投票后避免对帖子发表评论。
  • @H2CO3;谢谢 :)。每周我都会看到关于声称 VLA 不起作用(因为他们没有在 C99 模式下编译他们的程序)或这是什么类型的问题(不知道 VLA)。 :)
  • 因为“这个广泛可用的标准功能在双重过时的 C 版本中不起作用,因此使用复杂的非本地解决方法更好”是错误。这个答案是错误的,除非问题是关于 C89,它不是:它是关于 C(和 C++)。 C 有一个特性可以做到这一点,这个特性就是 VLA。
【解决方案3】:

在(C99 之前的)C 和 C++ 中,所有类型都是静态大小的。这意味着数组必须声明为常量且编译器知道的大小。

现在,许多 C++ 编译器提供动态大小的数组作为非标准扩展,C99 明确允许它们。所以int b[n] 如果你尝试一下,很可能会奏效。但在某些情况下,它不会,在这些情况下编译器并没有错。

【讨论】:

    【解决方案4】:

    如果你在编译时知道SIZE

    int ar[SIZE];
    

    如果你不这样做:

    std::vector<int> ar;
    

    我不想在您的 C++ 代码中的任何地方看到 malloc。但是,您从根本上说是正确的,对于 C,这正是您应该做的:

    int* ptr = malloc(sizeof(int) * SIZE);
    /* ... */
    free(ptr);
    

    可变长度数组是 GCC 扩展,允许您执行以下操作:

    int ar[n];
    

    但是我遇到了 VLA 被禁用但 GCC 没有成功检测到我正在尝试使用它们的问题。混乱随之而来。避免它。

    【讨论】:

    • 如果不需要在函数外部使用数组,则绝对没有理由在 C (>=99) 中使用 malloc()。此外,“可变长度数组是 GCC 扩展”仅适用于 C++(您的回答并不清楚)。
    【解决方案5】:

    Q1:第一个定义是静态数组声明。完全正确。 这是当您知道大小时,因此无法与 VLA 或 malloc() 进行比较。

    Q2:将大小作为用户输入时哪个更好:VLA 或 malloc。

    VLA : 它们受到环境对自动大小的限制 分配。而自动变量通常分配在堆栈上,相对
    小。限制是特定于平台的。此外,这仅在 c99 及更高版本中。通过 VLA 获得在声明多维数组时的一些易用性。

    Malloc :从堆中分配。所以,大尺寸肯定更好。因为,涉及多维数组指针,所以实现有点复杂。

    查看http://bytes.com/topic/c/answers/578354-vla-feature-c99-vs-malloc

    【讨论】:

      【解决方案6】:

      我认为metod1可能会快一点,但它们在C语言中都是正确的。

      在 C++ 中,第一个可以工作,但如果你想使用第二个,你应该使用:

       int size = 5;
       int * array = new int[size];
      

      记得删除它:

       delete [] array;
      

      【讨论】:

        【解决方案7】:

        我认为它为您提供了更多在编码时使用的选择。

        如果使用malloc或其他动态分配来获取指针。您将使用 p+n...,但如果您使用数组,则可以使用array[n]。此外,在定义指针时,您需要释放它;但数组不需要free

        在 C++ 中,我们可以定义用户定义的类来做这些事情,而在 STL 中,有 std::vector 可以做数组的事情,等等。

        【讨论】:

          【解决方案8】:

          两者都是正确的。您使用的声明取决于您的代码。

          第一个声明,即int a[size]; 创建一个固定大小为 20 个元素的数组。 当您知道将在代码中使用的数组的确切大小时,这会很有帮助。例如,您正在生成 一个数字表 n 直到它的第 20 个倍数。

          第二个声明允许您创建所需大小的数组。 当您需要一个不同大小的数组时,这很有帮助,例如,每次执行代码时,您想要生成斐波那契数列直到n。在这种情况下,对于n 的每个值,数组的大小必须为n。所以假设你有n = 5,在这种情况下int a [20] 将浪费内存,因为只有前五个槽将用于斐波那契数列,其余槽将为空。同样,如果n = 25 那么您的数组int a[20] 将变得太小。

          【讨论】:

            【解决方案9】:

            如果您使用 malloc 定义数组,不同之处在于,您可以动态传递数组的大小,即在运行时。您输入程序在运行时具有的值。 另一个区别是使用 malloc 创建的数组在堆上分配空间。因此,与静态数组不同,它们在函数调用中被保留。

            例子-

                   #include<stdio.h>
                   #include<stdlib.h>
                   int main()
                   {
                       int n;
                       int *a;
                       scanf("%d",&n);
                       a=(int *)malloc(n*sizeof(int));
                       return 0;
                   }
            

            【讨论】:

            • 如果使用 malloc 定义数组,则可以动态传递数组的大小,即在运行时:VLA 也是如此。
            • 不要转换malloc()的返回值。
            • @H2CO3 是的,我知道没有必要在 C 中强制转换,但是这样做并没有什么坏处,对吧?
            • @NeerajKumar 但是确实如此。 It hurts badly (link)。它降低了可读性并且可以隐藏错误。它没有任何好处,只有丑陋和危险。
            猜你喜欢
            • 2012-04-08
            • 2011-11-30
            • 2017-03-13
            • 2014-04-10
            • 2010-10-23
            • 2023-03-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多