En programación de computadoras , una matriz de longitud variable ( VLA ), también llamada de tamaño variable o tamaño en tiempo de ejecución , es una estructura de datos de matriz cuya longitud se determina en tiempo de ejecución (en lugar de en tiempo de compilación). [1] En C, se dice que el VLA tiene un tipo modificado de forma variable que depende de un valor (ver Tipo dependiente ).
El objetivo principal de los VLA es simplificar la programación de algoritmos numéricos.
Los lenguajes de programación que admiten VLA incluyen Ada , Algol 68 (para filas no flexibles), APL , C99 (aunque posteriormente relegado en C11 a una característica condicional, que las implementaciones no están obligadas a admitir; [2] [3] en algunas plataformas, podría implementarse previamente con alloca()
o funciones similares) y C # (como arreglos asignados a pila en modo inseguro), COBOL , Fortran 90 , J y Object Pascal (el lenguaje usado en Borland Delphi y Lazarus, que usa FPC).
Memoria
Asignación
- El compilador GNU C asigna memoria para VLA con duración de almacenamiento automático en la pila . [4] Esta es la opción más rápida y sencilla en comparación con la asignación de almacenamiento dinámico, y la utilizan la mayoría de los compiladores.
- Los VLA también se pueden asignar en el montón y acceder internamente mediante un puntero a este bloque.
Implementación
C99
La siguiente función C99 asigna una matriz de longitud variable de un tamaño especificado, la llena con valores de punto flotante y luego la pasa a otra función para su procesamiento. Debido a que la matriz se declara como una variable automática, su vida útil finaliza cuando read_and_process()
regresa.
float read_and_process ( int n ) { float vals [ n ]; para ( int i = 0 ; i < n ; ++ i ) vals [ i ] = read_val (); proceso de devolución ( n , vals ); }
En C99, el parámetro de longitud debe ir antes del parámetro de matriz de longitud variable en las llamadas a funciones. [1] En C11, __STDC_NO_VLA__
se define una macro si no se admite VLA. [5] GCC tenía VLA como una extensión antes de C99.
Linus Torvalds ha expresado su disgusto en el pasado por el uso de VLA para arreglos con tamaños pequeños predeterminados porque genera código de ensamblaje de menor calidad. [6] Con el kernel de Linux 4.20, el kernel de Linux está efectivamente libre de VLA. [7]
Aunque C11 no nombra explícitamente un límite de tamaño para los VLA, algunas lecturas creen que debería tener el mismo tamaño máximo que todos los demás objetos, es decir, SIZE_MAX bytes. [8] Sin embargo, esta lectura debe entenderse en el contexto más amplio de los límites del entorno y la plataforma, como el tamaño de página típico de protección de pila de 4 KiB, que es muchos órdenes de magnitud menor que SIZE_MAX.
Ada
El siguiente es el mismo ejemplo en Ada . Las matrices Ada llevan consigo sus límites, por lo que no es necesario pasar la longitud a la función Process.
type Vals_Type es una matriz ( rango positivo <>) de Float ; función Read_And_Process ( N : Integer ) return Float es Vals : Vals_Type ( 1 .. N ); comenzar para I en 1 .. N loop Vals ( I ) : = Read_Val ; ciclo final ; Proceso de devolución ( Vals ); end Read_And_Process ;
Fortran 90
La función equivalente de Fortran 90 es
función read_and_process ( n ) resultado ( o ) integer , intent ( in ) :: n real :: o real , dimensión ( n ) :: vals entero :: i do i = 1 , n vals ( i ) = read_val () end do o = process ( vals ) end function read_and_process
cuando se utiliza la función Fortran 90 de verificar las interfaces de los procedimientos en el momento de la compilación; por otro lado, si las funciones usan una interfaz de llamada anterior a Fortran 90, las funciones (externas) deben declararse primero y la longitud de la matriz debe pasarse explícitamente como un argumento (como en C):
función read_and_process ( n ) resultado ( o ) integer , intent ( in ) :: n real :: o real , dimension ( n ) :: vals real :: read_val , proceso entero :: i do i = 1 , n vals ( i ) = read_val () end do o = process ( vals , n ) end function read_and_process
Cobol
El siguiente fragmento COBOL declara una matriz de registros de longitud variable que DEPT-PERSON
tienen una longitud (número de miembros) especificada por el valor de PEOPLE-CNT
:
DIVISIÓN DE DATOS . SECCIÓN TRABAJO-ALMACENAMIENTO . 01 DEPARTAMENTO-PERSONAS . 05 PEOPLE-CNT PIC S9 (4) BINARIO . 05 DEPT-PERSON OCURRE DE 0 A 20 VECES DEPENDIENDO DE PEOPLE-CNT . 10 FOTO DE NOMBRE DE PERSONA X (20) . 10 PERSON-WAGE PIC S9 (7) V99 PACKED-DECIMAL .
El COBOL VLA, a diferencia de la de otros idiomas menciona aquí, es seguro porque COBOL requiere uno para especificar el tamaño de la matriz máxima - en este ejemplo, DEPT-PERSON
no puede tener más de 20 artículos, independientemente del valor de PEOPLE-CNT
.
C#
El siguiente fragmento de C # declara una matriz de enteros de longitud variable. Antes de la versión 7.2 de C #, se requiere un puntero a la matriz, lo que requiere un contexto "inseguro". La palabra clave "inseguro" requiere que un ensamblado que contenga este código se marque como inseguro.
inseguro void DeclareStackBasedArrayUnsafe ( int tamaño ) { int * pArray = stackalloc int [ tamaño ]; pArray [ 0 ] = 123 ; }
La versión 7.2 de C # y posteriores permiten que la matriz se asigne sin la palabra clave "inseguro", mediante el uso de la función Span. [9]
void DeclareStackBasedArraySafe ( int tamaño ) { Span < int > stackArray = stackalloc int [ tamaño ]; stackArray [ 0 ] = 123 ; }
Objeto Pascal
En este idioma, se llama matriz dinámica. La declaración de dicha variable es similar a la declaración de una matriz estática, pero sin especificar su tamaño. El tamaño de la matriz se da en el momento de su uso.
programa CreateDynamicArrayOfNumbers ( Tamaño : Integer ) ; var NumberArray : matriz de LongWord ; begin SetLength ( NumberArray , Size ) ; NumberArray [ 0 ] : = 2020 ; final .
La eliminación del contenido de una matriz dinámica se realiza asignándole un tamaño de cero.
... SetLength ( NumberArray , 0 ) ; ...
Referencias
- ^ a b "Matrices de longitud variable" . Archivado desde el original el 26 de enero de 2018.
- ^ "Longitud variable: uso de la colección de compiladores GNU (GCC)" .
- ^ ISO 9899: 2011 lenguajes de programación - C 6.7.6.2 4.
- ^ "Opciones de generación de código - El compilador GNU Fortran" .
- ^ § 6.10.8.3 del estándar C11 (n1570.pdf)
- ^ "LKML: Linus Torvalds: Re: eliminación de VLA (era Re: [RFC 2/2] lustre: use VLA_SAFE)" . lkml.org .
- ^ "El kernel de Linux ahora está libre de VLA: una victoria para la seguridad, menos gastos generales y mejor para Clang - Phoronix" . www.phoronix.com .
- ^ §6.5.3.4 y §7.20.3 del estándar C11 (n1570.pdf)
- ^ "operador stackalloc (referencia de C #)" . Microsoft.