关于Java和C#中多维数组的问题?

关于Java和C#中多维数组的问题?,c#,java,c,multidimensional-array,C#,Java,C,Multidimensional Array,在Java或C#编程语言中,我们可以声明多维数组,如下所示: int[][] arr = new int[2][]; arr[0] = new int[3]; arr[1] = new int[4]; 我想知道代码内部的内存分配机制,特别是它们与C编程语言之间的区别?因为您使用的是常量,编译器(应该)将所有请求合并到一个分配中,只需在可执行文件本身(.bss部分)中创建一个静态块,为数组保留内存。对于动态分配,可能(在幕后)使用malloc为数组分配内存。对于动态大小的数组,C#和Java等语

在Java或C#编程语言中,我们可以声明多维数组,如下所示:

int[][] arr = new int[2][];
arr[0] = new int[3];
arr[1] = new int[4];

我想知道代码内部的内存分配机制,特别是它们与C编程语言之间的区别?

因为您使用的是常量,编译器(应该)将所有请求合并到一个分配中,只需在可执行文件本身(.bss部分)中创建一个静态块,为数组保留内存。对于动态分配,可能(在幕后)使用malloc为数组分配内存。对于动态大小的数组,C#和Java等语言还需要存储其他元数据,如大小,因此我无法确切地告诉您它将使用多少内存。我相信静态大小的数组也需要大小,因为运行时边界检查。

由于使用常量,编译器(应该)将所有请求合并到一个分配中,只需在可执行文件本身(.bss部分)中创建一个静态块,为数组保留内存。对于动态分配,可能(在幕后)使用malloc为数组分配内存。对于动态大小的数组,C#和Java等语言还需要存储其他元数据,如大小,因此我无法确切地告诉您它将使用多少内存。我相信静态大小的数组也需要调整大小,因为需要进行运行时边界检查。

我只能从Java的角度进行讨论,但我相信C#的工作方式基本相同(如果不是这样的话,请有人纠正我)

声明和分配数组与在执行过程中的哪个点执行的操作是不同的

当您声明数组类型的变量时,它包含对对象的引用。这不会创建数组对象或为其组件分配空间,而只是变量本身。但是初始化器可以创建一个数组,该数组随后成为变量的初始值。例如:

//only has a variable of firstArray (i.e. doesn't create array,
//therefore array memory not used)

int[] firstArray; 

//creates variable secondArray and allocates 4 int
//values to the array

int[] secondArray = { 1, 2, 3, 4 }; 
//Creates an array of 5 Object's which will all
//be null.

Object[] objectArray = new Object[5];  
参考:

当分配的数组没有特定值时,所有元素都会收到数组数据类型的默认值(例如,对于布尔值,它将为false,0表示int,等等),例如:

//only has a variable of firstArray (i.e. doesn't create array,
//therefore array memory not used)

int[] firstArray; 

//creates variable secondArray and allocates 4 int
//values to the array

int[] secondArray = { 1, 2, 3, 4 }; 
//Creates an array of 5 Object's which will all
//be null.

Object[] objectArray = new Object[5];  
参考:&JLS

这里还有一些多维数组示例:

//This is allocating an int[] array inside myArray at position [0]
int[][] myArray = { { 1, 2 } };

for (int[] i : myArray)
    for (int j : i)
      System.out.println(j);  //will print 1 then 2;
要使用您的示例之一:

//This is declaring a multi-dimensional array of int with a max length of 2
int[][] arr = new int[2][]; //Only declaration, no memory allocation for array components

arr[0] = new int[] {1, 2};  //Allocating memory
arr[1] = new int[] {3, 4};  //Allocating memory

for(int[] i : arr)
  for(int j: i)
    System.out.println(j);  //Will print 1 then 2 then 3 then 4...

我只能从Java的角度来谈,但我相信C#的工作原理基本相同(如果不是这样的话,请有人纠正我)

声明和分配数组与在执行过程中的哪个点执行的操作是不同的

当您声明数组类型的变量时,它包含对对象的引用。这不会创建数组对象或为其组件分配空间,而只是变量本身。但是初始化器可以创建一个数组,该数组随后成为变量的初始值。例如:

//only has a variable of firstArray (i.e. doesn't create array,
//therefore array memory not used)

int[] firstArray; 

//creates variable secondArray and allocates 4 int
//values to the array

int[] secondArray = { 1, 2, 3, 4 }; 
//Creates an array of 5 Object's which will all
//be null.

Object[] objectArray = new Object[5];  
参考:

当分配的数组没有特定值时,所有元素都会收到数组数据类型的默认值(例如,对于布尔值,它将为false,0表示int,等等),例如:

//only has a variable of firstArray (i.e. doesn't create array,
//therefore array memory not used)

int[] firstArray; 

//creates variable secondArray and allocates 4 int
//values to the array

int[] secondArray = { 1, 2, 3, 4 }; 
//Creates an array of 5 Object's which will all
//be null.

Object[] objectArray = new Object[5];  
参考:&JLS

这里还有一些多维数组示例:

//This is allocating an int[] array inside myArray at position [0]
int[][] myArray = { { 1, 2 } };

for (int[] i : myArray)
    for (int j : i)
      System.out.println(j);  //will print 1 then 2;
要使用您的示例之一:

//This is declaring a multi-dimensional array of int with a max length of 2
int[][] arr = new int[2][]; //Only declaration, no memory allocation for array components

arr[0] = new int[] {1, 2};  //Allocating memory
arr[1] = new int[] {3, 4};  //Allocating memory

for(int[] i : arr)
  for(int j: i)
    System.out.println(j);  //Will print 1 then 2 then 3 then 4...

这不是一个完整的答案,但Java虚拟机有自己的分配多维数组的指令。从中查看multianewarray


如果调用
newint[1][2][]
编译器将生成具有维度为1和2的multianewarray指令的字节码,类型为int[][].

这不是一个完整的答案,但Java虚拟机有自己的分配多维数组的指令。从中查看multianewarray


如果调用
newint[1][2][]
编译器将生成具有维度为1和2的multianewarray指令的字节码,类型为int[][].

在Java中,所有这些分配都在堆上,因此您的代码与C代码相同:

int **arr=malloc(2*sizeof(int*));
arr[0]=malloc(3*sizeof(int));
arr[1]=malloc(4*sizeof(int));

编辑:我不是Java专家,但我认为在Java中,新数组的成员被初始化为0(或null),因此calloc比malloc(在我的代码中)更正确。

在Java中,所有这些分配都在堆上,因此您的代码与C代码相同:

int **arr=malloc(2*sizeof(int*));
arr[0]=malloc(3*sizeof(int));
arr[1]=malloc(4*sizeof(int));

编辑:我不是Java专家,但我认为在Java中,新数组的成员被初始化为0(或null),因此calloc比malloc(在我的代码中)更正确。

好奇是很好的,但为什么你想知道?内存分配机制是什么意思?您应该了解的一点是,C#,Java在虚拟运行时上运行,而C编译为本机。虚拟机使用与编译代码相同的调用。因此,这三个系统的实际内存分配是相同的。但是在运行时内,它们有不同的内存分配机制。对于所使用的内存大小,请检查C#中名为sizeof的方法。C中的内存分配机制基本相同。唯一的区别是C既支持指向数组的指针数组,也支持数组或数组。Java和C#支持数组的引用数组。好奇是很好的,但为什么你想知道?内存分配机制是什么意思?您应该了解的一点是,C#,Java在虚拟运行时上运行,而C编译为本机。虚拟机使用与编译代码相同的调用。因此,这三个系统的实际内存分配是相同的。但是在运行时内,它们有不同的内存分配机制。对于所使用的内存大小,请检查C#中名为sizeof的方法。C中的内存分配机制基本相同。唯一的区别是C既支持指向数组的指针数组,也支持数组或数组。Java和C#支持数组引用数组。