【问题标题】:create an array whose length is determined by user input: C vs C99 vs Java创建一个长度由用户输入确定的数组:C vs C99 vs Java
【发布时间】:2018-05-23 17:35:32
【问题描述】:

我正在尝试找出在 C 和 Java 中创建长度在运行时(例如,通过用户输入)确定的数组的方法。

在 C 中,我知道某些版本的 C 标准(例如 C99)现在允许以下方式:

int size;
scanf("%d",&size);
int arr[size];

但是,理论上,像这样在 C 中创建动态数组是不可接受的。全局解决方案是在 C 中使用 malloc()。

我的问题是,在 Java 中呢?我在自己的计算机上运行了以下 Java 程序,没有产生错误。但我不确定它是否仅适用于特定的 Java 平台(如 C 案例中的 C99)还是在所有 Java 中都可以普遍接受

import java.util.Scanner;

public class Main{
    public static void main(String[] args){

    int size;

    System.out.println("enter a number:");
    Scanner s = new Scanner(System.in);
    size = s.nextInt();

    int[] arr = new int[size];
    }
}

【问题讨论】:

  • 我认为以这种方式分配数组大小没有任何问题
  • @YassinHajaj No. c99 是 C 标准的一个版本。其他C标准包括c11等
  • Java 中数组的行为和工作方式已完全指定,请参阅Java Language Specification version 10, chapter 10。坦率地说,我很惊讶你甚至认为 Java - 一种完全托管的语言 - 会以某种方式跳过数组。
  • int arr[size]; 不是动态数组。它是一个自动数组,其大小在运行时确定。自动对象的生命周期仅延伸到执行离开声明它的块的那一刻。动态对象在显式被释放之前一直存在。

标签: java c c99


【解决方案1】:

在 java 中,您可以设置数组的长度,因为数组的创建是在运行时执行的,并且应该在所有 java 平台中都被接受。

【讨论】:

    【解决方案2】:

    这是完全可以接受的,并且通常在 Java 中完成。 new int[number] 在运行时执行,动态数字会执行此操作。

    只要数组的长度是非负的int,这在Java中是有效的。

    【讨论】:

    • 即使是负整数,也是有效的Java。它会在运行时失败;但如果它对于可用内存来说太大,则可能是一个正整数。 (另外,您的意思是非负数,非正数:零是数组的合适长度)。 (此外,长度不必是 int;它只需是经过一元数字提升为 int 的类型。
    • 那么数组是分配在堆上还是栈上呢?我知道在 C/C++ 中,静态数组分配在堆栈上,而动态数组分配在堆上。但是在 Jave 中,它看起来像是创建静态数组(例如 int[] static_arr = new int[5])和动态数组(例如 int[] dynamic_arr = new int[n]; // n 确定的方法通过用户输入)是相同的。那么它们是否都分配在堆上而不是一个在堆栈上和一个在堆上? @Ernest Kiwele
    • @Jane Java 数组是对象,所以它们总是堆分配的。
    • @AndyTurner 关于非负长度的好点,我已经编辑过了。关于通过编译时验证的负 int,这很明显,但我认为问题更多是关于数组创建的动态方面。在运行时发生错误的可能原因有很多,但这并不会使动态创建本质上存在问题。
    【解决方案3】:

    在 Java 中,数组是在堆上分配的。如果分配失败,则会抛出一个可捕获的异常!可以从失败的数组分配中恢复。

    % java Main
    enter a number:
    1231231231
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
            at Main.main(Main.java:12)
    

    捕捉异常:

    try {
        int[] arr = new int[size];
    } catch (OutOfMemoryError e) {
        System.out.println("Alas, such array could not be allocated. Try a smaller number next time!");
    }
    

    你得到

    % java Main      
    enter a number:
    1231231231
    Alas, such array could not be allocated. Try a smaller number next time!
    

    在 C99 中简单地使用可变长度数组经常不受欢迎的原因是数组是在 stack 上分配的。现在,如果数组的大小来自用户,很容易造成无法控制的崩溃:

    #include <stdio.h>
    
    int main(void) {
        int size;
        scanf("%d", &size);
        volatile int arr[size];
        printf("%d\n", arr[size - 1]);
    }
    

    现在编译并运行:

    % ./a.out    
    1231231231  
    zsh: segmentation fault (core dumped)  ./a.out
    

    没有办法检查分配是否成功。因此,如果您不确定 - 尤其是在处理可能来自不受信任用户的数字时,您不应该使用堆栈分配的可变长度数组。

    【讨论】:

    • 当然,来自乐观内存分配的段错误完全不同。 :-)
    • @rici:我希望看到 C 标准要求实现文档“环境要求”,然后说如果满足环境条件并且程序不调用 UB,则实现必须要么表现由标准定义或以实现定义的方式失败。如果 C 编译器指定操作系统必须让程序运行的环境要求,但操作系统出于该程序无法控制的原因终止进程,则此类操作将违反记录的环境要求,从而放弃对实施的任何要求。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多