¿Por qué no se puede hacer variable el tamaño de una matriz estática?

6 minutos de lectura

avatar de usuario
Abhinav

Relacionado pero no del todo duplicado, ya que analiza C ++:

¿Podemos darle al tamaño de la matriz estática una variable?

Estoy definiendo una matriz en uno de los archivos secundarios de la siguiente manera.

static int arr[siz];

Aquí siz es una variable global disponible para el archivo secundario. Pero el compilador gcc produce el siguiente error:

<filename>: <line_num> : error : storage size of ‘arr’ isn’t constant

¿Por qué no puedo definir un static matriz de tamaño variable?

EDITAR: Esto parece ser un problema solo para static int escribe. Si cambio el tipo de variable de arr desde static int para intel error desaparece, aunque el tamaño de la matriz aún depende de una variable siz.

avatar de usuario
Guardar

Dado que el tamaño de la matriz que declara no es constante, lo que tiene es un Matriz de longitud variable (VLA). Los VLA están permitidos por el estándar c99, pero existen algunas limitaciones asociadas con él. No puede tener una matriz de longitud variable con static o extern especificador de clase de almacenamiento.

Tienes un VLA con static especificación de almacenamiento y no está permitido por el estándar C99.

Referencia:

estándar c99: 6.7.5.2/8

EJEMPLO 4 Todas las declaraciones de tipos modificados de forma variable (VM) tienen que estar en el ámbito de bloque o en el ámbito de prototipo de función. Los objetos de matriz declarados con el especificador de clase de almacenamiento estático o externo no pueden tener un tipo de matriz de longitud variable (VLA). Sin embargo, un objeto declarado con el especificador de clase de almacenamiento estático puede tener un tipo de VM (es decir, un puntero a un tipo de VLA). Finalmente, todos los identificadores declarados con un tipo de VM tienen que ser identificadores ordinarios y no pueden, por lo tanto, ser miembros de estructuras o uniones.

Entonces, si desea una matriz de tamaño dinámico con static especificador de almacenamiento, tendrá que usar una matriz dinámica asignada en el montón.

#define MAX_SIZE 256
static int* gArr;
gArr = malloc(MAX_SIZE * sizeof(int));

EDITAR:

Para responder a su pregunta actualizada:
Cuando quitas el static palabra clave de la declaración, el especificador de almacenamiento de la matriz declarada cambia de static a global, tenga en cuenta la cita estándar anterior, menciona claramente la restricción de que los VLA no están permitidos con static y extern especificación de almacenamiento. Claramente, puede tener un VLA con especificación de almacenamiento global, que es lo que tiene una vez que elimina el static palabra clave.

  • Gracias por la respuesta bien investigada.

    – Abhinav

    20 mayo 2012 a las 18:11

  • Entonces, si estoy usando gcc-4.3, ¿los VLA no están permitidos para variables de tipo externo y estático? Esto es lo que el usuario DCoder también ha respondido en un comentario en otra respuesta.

    – Abhinav

    20 mayo 2012 a las 19:20


  • @Abhinav: Sí, tienes razón. No se permiten VLA para variables con extern y static escriba la especificación de almacenamiento. Está utilizando gcc-4.3 que cumple con el estándar c99. Actualizó la respuesta para abordar su consulta editada.

    – Alok Guardar

    21 de mayo de 2012 a las 2:54


  • Existe cierta ambigüedad sobre el significado de “constante”, al menos con mi compilador (gcc 6.3.0). Incluso si lo hago const size_t siz = 3; que claramente no es variable y se puede evaluar en tiempo de compilación, aún recibiría un error con static char arr[siz]; lo que parece bastante limitante. Por cierto, en mi caso, estaba tratando de usar sizeof() en una cadena fija, para mantenimiento y autodocumentación.

    – Nagev

    17/10/2017 a las 15:42

avatar de usuario
eitan t

Está asignando la matriz en tiempo de compilación, por lo que el compilador debe conocer el tamaño de la matriz por adelantado. tienes que declarar siz como una expresión constante antes de declarar arrpor ejemplo:

#define siz 5

o

enum ESizes
{
    siz = 5
};

Alternativamente, si necesita determinar su tamaño en tiempo de ejecución, puede asignarlo en el montón usando malloc:

static int* arr;
arr = (int*)malloc(siz * sizeof(int))

EDITAR: como ha mencionado eddieantonio, mi respuesta es válida para C89. En C99 se permite declarar arreglos de tamaño variable.

  • @HeathRaftery Tienes toda la razón (tenía en mente C ++ al escribir esto, olvidé que la pregunta es sobre C). Ejemplo eliminado. Gracias por traer esto a mi atención.

    – Eitan T.

    19 de marzo de 2018 a las 22:47

No puede definir ninguna matriz de tamaño variable. Eso es porque arr[siz] hace que el compilador (!) asigne memoria para su arreglo (bueno, el compilador crea un programa, eso…, pero no entremos en detalles). Sin embargo, las variables se pueden cambiar en tiempo de ejecución (!), lo que significa que el compilador no tiene posibilidad de saber cuánta memoria asignar.

lo que puedes hacer es

static int* arr;
arr = (int*) calloc(siz,sizeof(int))

Estas líneas dan como resultado un programa que asigna memoria en tiempo de ejecución, por lo tanto, su tamaño exacto también puede definirse en tiempo de ejecución.

  • C99 permite matrices de longitud variable, siempre que no sean estáticas ni externas. “Todas las declaraciones de tipos modificados de forma variable (VM) deben estar en el alcance del bloque o en el alcance del prototipo de la función. Los objetos de matriz declarados con el especificador de clase de almacenamiento estático o externo no pueden tener un tipo de matriz de longitud variable (VLA)”.

    – DCoder

    20 de mayo de 2012 a las 17:16

  • @DCoder Estoy usando gcc 4.3. Gracias por el comentario constructivo.

    – Abhinav

    20 de mayo de 2012 a las 17:48

  • @ user1129682 Lo siento, tuve que volver a abrir la pregunta. Por favor, lea la pregunta editada.

    – Abhinav

    20 de mayo de 2012 a las 19:12

  • El problema básico siempre es lo que mencioné en mi respuesta: en el momento de la compilación, no está claro cuáles serán los valores en tiempo de ejecución y qué efecto pueden tener los valores. Per se, en una vista simple, simple e ingenua, es por eso que acceder a valores definidos en tiempo de ejecución en tiempo de compilación produce un error. Para abreviar: con la lógica y la magia del compilador, esta incertidumbre se puede eliminar y el compilador hará que funcione.

    – usuario1129682

    21 de mayo de 2012 a las 7:23


avatar de usuario
vvnraman

No puede declarar un static matriz de tamaño variable porque su espacio está asignado en el Segmento de datos (o segmento bss en caso de una variable no inicializada). Por lo tanto, el compilador necesita conocer el tamaño en el momento de la compilación y se quejará si el tamaño no es una constante.

La razón subyacente de esto es que el tamaño del segmento de datos contribuye al tamaño del ejecutable que se genera, que obviamente se crea en el momento de la compilación y, por lo tanto, debe corregirse.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad