¿Cómo funciona sizeof (array) en tiempo de ejecución?

6 minutos de lectura

He leído que el operador sizeof en C se interpreta en tiempo de compilación y dado que en tiempo de compilación el compilador conoce el tamaño de la matriz y su tipo, sizeof puede calcular la cantidad de bytes ocupados por la matriz. Pero, ¿cómo funciona sizeof para el siguiente código?

 #include<stdio.h>
 #include<string.h>
 int main()
 {
    int n;
    scanf("%d",&n);
    int a[n];
    int s=sizeof(a);
    printf("%d",s);
    return 0;
 }

Aquí el tamaño de la matriz no se conoce en el momento de la compilación, entonces, ¿cómo funciona correctamente?

  • posible duplicado de Usar sizeof con una matriz asignada dinámicamente

    – bola mate

    9 de abril de 2012 a las 19:06

  • Los arreglos de longitud variable son una excepción, para ellos, sizeof se evalúa en tiempo de ejecución, no en tiempo de compilación.

    –Daniel Fischer

    9 de abril de 2012 a las 19:06

  • @MДΓΓБДLL No, ese es sobre malloced material, no sobre VLA.

    –Daniel Fischer

    9 de abril de 2012 a las 19:07

  • @MДΓΓБДLL: Su posible duplicado está lidiando con una situación diferente (malloc()no un VLA, matriz de longitud variable).

    –Jonathan Leffler

    9 de abril de 2012 a las 19:07

sizeof siempre se calcula en tiempo de compilación en C89. Desde C99 y las matrices de longitud variable, se calcula en tiempo de ejecución cuando una matriz de longitud variable es parte de la expresión en el sizeof operando

Lo mismo para la evaluación de la sizeof operando: no se evalúa en C89 pero en C99 si el operando es de tipo array de longitud variable se evalúa. Por ejemplo:

int n = 5;
sizeof (int [n++]); 

// n is now 6

  • Qué significa eso int [n++]? Primera vez que lo veo en lenguaje C.

    – La máscara

    9 de junio de 2013 a las 21:45

  • @La máscara int [N] es un nombre de tipo C. es una matriz N de int. Cuándo N no es una constante como en la respuesta, es una matriz de longitud variable.

    – ouah

    9 de junio de 2013 a las 21:49

  • @ouah: desde antes, hemos estudiado que la expresión dentro del operador sizeof realmente no evalúa. es decir. sizeof(n++) dejará n a 5 (si n=5 inicialmente). entonces, ¿por qué el valor de n cambia aquí?

    – rforritz

    12 de junio de 2013 a las 21:27

  • El operando de tipo matriz de longitud variable @rforritz es una excepción a esta regla, en este caso se evalúa el operando

    – ouah

    12/06/2013 a las 21:33

avatar de usuario
zwol

Ya que estás aplicando sizeof a una matriz de longitud variable, cuyo tamaño no se conoce por completo en tiempo de compilación, el compilador debe generar código para hacer parte de él en tiempo de ejecución.

Los optimizadores de alto nivel de gcc 4.6.3 convierten el código que mostraste en

scanf ("%d", &n);
t12 = (long unsigned int) n;
t13 = t12 * 4;
__builtin_alloca (t13);
t16 = (unsigned int) t12;
t17 = t16 * 4;
s18 = (int) t17;
printf ("%d", s18);

¿Eso explica lo que está pasando debajo del capó? (No se desanime por la cantidad de variables temporales que parecen tontas; eso es un artefacto del programa que está en funcionamiento). asignación única estática formulario en el punto donde pedí un volcado de código intermedio).

  • Coloque el archivo que desea compilar en un directorio por sí mismo, luego invoque gcc desde un shell en ese directorio, agregando -fdump-tree-all a las opciones de la línea de comandos (probablemente desee -S y -O2 así como). Debe aislar el archivo en un directorio temporal porque esto generará aproximadamente 100 archivos de código intermedio (y eso es solo la primera mitad de la canalización de optimización; -fdump-rtl-all le dará otros archivos 60ish). Luego puede leerlos en secuencia (están numerados)

    – zwol

    19 de junio de 2013 a las 3:02

  • @TheMask (continuación) Los volcados de “árbol” son generalmente más útiles que los volcados de “rtl” a menos que esté intentando depurar uno de los “back-end” de GCC (generación de código para una arquitectura específica). Puede limitar la salida a un pase específico de interés diciendo -fdump-(tree|rtl)-PASSNAME en lugar de -all, donde CONTRASEÑA es la palabra después del número en el nombre del archivo de volcado. Ver gcc.gnu.org/onlinedocs/gcc-4.8.1/gcc/… (desplácese un poco hacia arriba, luego lea desde allí hasta el final del documento) para obtener más detalles.

    – zwol

    19 de junio de 2013 a las 3:07

  • @TheMask … Probablemente también debería señalarte el manual interno para gcc que explica qué son las representaciones intermedias y cómo funcionan.

    – zwol

    19 de junio de 2013 a las 3:09

  • ¡Muchas gracias! Revisaré todo esto. 🙂

    – La máscara

    22 de junio de 2013 a las 13:14

Del estándar C99:

6.5.3.4

los sizeof El operador produce el tamaño (en bytes) de su operando, que puede ser una expresión o el nombre entre paréntesis de un tipo. El tamaño se determina a partir del tipo de operando. El resultado es un número entero. Si el tipo del operando es un tipo de matriz de longitud variable, el operando se evalúa; de lo contrario, el operando no se evalúa y el resultado es una constante entera.

avatar de usuario
greg hewgill

En ese caso, sizeof() se evalúa en tiempo de ejecución. El compilador, porque sabe que el tamaño de a se basa en el valor de n en el momento de la declaración de la matriz, genera código para usar el valor apropiado de n para devolver un valor razonable para sizeof().

En C99, no todos los usos de sizeof() puede evaluarse completamente en tiempo de compilación y reducirse a una constante de tiempo de ejecución.

He leído que el operador sizeof en C se interpreta en tiempo de compilación

sizeof se determina en tiempo de compilación en todos los casos excepto para los VLA. Para un VLA, sizeof se evalúa en tiempo de ejecución.

  • De hecho (C11): “Si el tipo del operando es un tipo de matriz de longitud variable, el operando se evalúa; de lo contrario, el operando no se evalúa y el resultado es una constante entera”.

    – pmor

    22/11/2021 a las 16:00

avatar de usuario
R.. GitHub DEJAR DE AYUDAR A ICE

Independientemente de si sizeof se calcula en tiempo de compilación o tiempo de ejecución (o más formalmente hablando, ya sea que su resultado sea una expresión constante entera), el resultado de sizeof se basa puramente en la tipo de su argumento y no cualquier dato oculto que acompañe a la propia matriz de longitud variable. por supuesto cuando sizeof se aplica a un tipo modificado de forma variable, el programa generado debe realizar un seguimiento de ese tamaño en alguna parte. Pero podría simplemente volver a calcularlo si la expresión fuera lo suficientemente simple y las variables de las que originalmente derivó la longitud no pueden haber cambiado. O bien, podría almacenar el tamaño del tipo en algún lugar (esencialmente en una variable local oculta), pero esto no estaría conectado al objeto VLA de ninguna manera observable (por ejemplo, si pasa un puntero al primer elemento del VLA a otra función, ese puntero no se puede usar para recuperar la longitud del VLA).

  • De hecho (C11): “Si el tipo del operando es un tipo de matriz de longitud variable, el operando se evalúa; de lo contrario, el operando no se evalúa y el resultado es una constante entera”.

    – pmor

    22/11/2021 a las 16:00

¿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