Articulo de referencia

tamaño de

sizeof es un operador unario en los lenguajes de programación C y C++ . Genera el tamaño de almacenamiento de una expresión o un tipo de datos , medido en el número de unidades ...

sizeof es un operador unario en los lenguajes de programación C y C++ . Genera el tamaño de almacenamiento de una expresión o un tipo de datos , medido en el número de unidades de tamaño char . En consecuencia, se garantiza que el constructo sizeof (char) sea 1. El número real de bits de tipo char se especifica mediante la macro de preprocesador CHAR_BIT , definida en el archivo de inclusión estándar limits.h . En la mayoría de las plataformas informáticas modernas, este es de ocho bits. El resultado de sizeof tiene un tipo entero sin signo que generalmente se denota por size_t .

El operador tiene un único operando, que puede ser una expresión o la conversión de un tipo de datos, que es un tipo de datos entre paréntesis. Los tipos de datos no solo pueden ser tipos primitivos , como tipos enteros y de punto flotante , sino también tipos de puntero y tipos de datos compuestos ( uniones , estructuras y clases de C++ ).

Objetivo

Muchos programas deben conocer el tamaño de almacenamiento de un tipo de datos en particular. Aunque para cualquier implementación dada de C o C++ el tamaño de un tipo de datos en particular es constante, los tamaños de incluso los tipos primitivos en C y C++ pueden definirse de manera diferente para diferentes plataformas de implementación. Por ejemplo, la asignación de espacio de matriz en tiempo de ejecución puede utilizar el siguiente código, en el que el operador sizeof se aplica a la conversión del tipo int :

int * puntero = malloc ( 10 * tamañode ( int ));       

En este ejemplo, la función malloc asigna memoria y devuelve un puntero al bloque de memoria. El tamaño del bloque asignado es igual a la cantidad de bytes de un único objeto de tipo int multiplicado por 10, lo que proporciona espacio para diez números enteros.

En general, no es seguro asumir el tamaño de ningún tipo de datos. Por ejemplo, aunque la mayoría de las implementaciones de C y C++ en sistemas de 32 bits definen el tipo int como cuatro octetos, este tamaño puede cambiar cuando el código se traslada a un sistema diferente, lo que puede romper el código. La excepción a esto es el tipo de datos char , que siempre tiene el tamaño 1 en cualquier implementación de C que cumpla con los estándares. Además, con frecuencia es difícil predecir los tamaños de los tipos de datos compuestos, como struct o union , debido al relleno. El uso de sizeof mejora la legibilidad, ya que evita las constantes numéricas sin nombre ( números mágicos ).

Una sintaxis equivalente para asignar el mismo espacio de matriz resulta de utilizar la forma desreferenciada del puntero a la dirección de almacenamiento, esta vez aplicando el operador a una variable puntero:

int * puntero = malloc ( 10 * tamaño de * puntero );       

Usar

El operador sizeof produce el espacio de almacenamiento de memoria requerido de su operando cuando se compila el código. El operando se escribe después de la palabra clave sizeof y puede ser el símbolo de un espacio de almacenamiento, por ejemplo, una variable, una expresión o un nombre de tipo. Los paréntesis para el operando son opcionales, excepto cuando se especifica un nombre de tipo. El resultado del operador es el tamaño del operando en bytes o el tamaño del requisito de almacenamiento de memoria. Para las expresiones, se evalúa como el tamaño de representación para el tipo que resultaría de la evaluación de la expresión, que no se realiza.

Por ejemplo, dado que sizeof (char) está definido como 1 [1] y asumiendo que el tipo entero tiene una longitud de cuatro bytes, el siguiente fragmento de código imprime1,4:

char c ; printf ( "%zu,%zu \n " , tamaño de c , tamaño de ( int )); 
     

Algunos archivos de encabezado estándar, como stddef.h , definen size_t para indicar el tipo entero sin signo del resultado de una expresión sizeof . El especificador de ancho de printf z tiene como objetivo dar formato a ese tipo.

sizeof no se puede utilizar en expresiones del preprocesador de C , como #if , porque es un elemento del lenguaje de programación, no de la sintaxis del preprocesador, que no tiene tipos de datos.

El siguiente ejemplo en C++ utiliza el operador sizeof con plantillas variádicas.

plantilla < typename ... Args > std :: size_t GetSize ( Args && ... args ) { /* Obtener el tamaño del paquete de parámetros.*/ std :: size_t Count = sizeof ... ( Args ); return Count ; }  
   

    
        
                

sizeof se puede utilizar con plantillas variádicas en C++11 y superior en un paquete de parámetros para determinar la cantidad de argumentos.

Aplicación a matrices

Cuando se aplica sizeof al nombre de una matriz, el resultado es la cantidad de bytes necesarios para almacenar la matriz completa. Esta es una de las pocas excepciones a la regla de que el nombre de una matriz se convierte en un puntero al primer elemento de la matriz, y es posible simplemente porque el tamaño real de la matriz es fijo y se conoce en tiempo de compilación, cuando se evalúa el operador sizeof . El siguiente programa utiliza sizeof para determinar el tamaño de una matriz declarada, evitando un desbordamiento de búfer al copiar caracteres:

#incluir <stdio.h> 

int principal ( int argc , char ** argv )    
{
  char buffer [ 10 ]; /* Matriz de 10 caracteres */  

  /* Copiar como máximo 9 caracteres desde argv[1] al búfer,
   * termina el buffer con valor nulo. */
  snprintf ( buffer , tamaño del buffer , "%s" , argv [ 1 ]);    

  devuelve 0 ; 
}

Aquí, sizeof buffer es equivalente a 10 * sizeof buffer [0] , que evalúa como 10, porque el tamaño del tipo char se define como 1.

C99 agrega soporte para miembros de matriz flexibles a las estructuras. Esta forma de declaración de matriz se permite solo como último elemento en las estructuras y se diferencia de las matrices normales en que no se especifica ninguna longitud al compilador. Para una estructura denominada s que contiene un miembro de matriz flexible denominado a , sizeof s es, por lo tanto, equivalente a offsetof (s, a) :

#incluir <stdio.h> 

estructura flexarray {  
    charval ; 
    int array []; /* Miembro de matriz flexible; debe ser el último elemento de la estructura */   
};

int principal ( int argc , char ** argv )    
{
    printf ( "tamañode(estructuraflexarray) == %zu \ n " , tamañode ( estructuraflexarray ));   
    devuelve 0 ; 
}

En este caso, el operador sizeof devuelve el tamaño de la estructura, incluido el relleno, pero sin ningún espacio de almacenamiento permitido para la matriz. La mayoría de las plataformas producen el siguiente resultado:

tamaño de (estructura flexarray) == 4

C99 también permite matrices de longitud variable que tienen la longitud especificada en tiempo de ejecución, [2] aunque la característica se considera una implementación opcional en versiones posteriores del estándar C. En tales casos, el operador sizeof se evalúa en parte en tiempo de ejecución para determinar el almacenamiento ocupado por la matriz.

#incluir <stddef.h> 

size_t flexsize ( int n ) { char b [ n + 3 ]; /* Matriz de longitud variable */ return sizeof b ; /* Tiempo de ejecución sizeof */ }  

         
       


int main ( void ) { size_t tamaño = flexsize ( 10 ); /* flexsize devuelve 13 */ devuelve 0 ; } 

      
   

sizeof se puede utilizar para determinar la cantidad de elementos de una matriz, dividiendo el tamaño de toda la matriz por el tamaño de un solo elemento. Esto se debe utilizar con precaución; al pasar una matriz a otra función, se "decaerá" a un tipo de puntero. En este punto, sizeof devolverá el tamaño del puntero, no el tamaño total de la matriz. Como ejemplo con una matriz adecuada:

int main ( void ) { int tab [ 10 ]; printf ( "Número de elementos en la matriz: %zu \n " , sizeof tab / sizeof tab [ 0 ]); /* produce 10 */ devuelve 0 ; }  

     
           
    

Tipos incompletos

sizeof solo se puede aplicar a tipos definidos "completamente". Con arreglos, esto significa que las dimensiones del arreglo deben estar presentes en su declaración y que el tipo de los elementos debe estar completamente definido. Para struct y union , esto significa que debe haber una lista de miembros de tipos completamente definidos. Por ejemplo, considere los siguientes dos archivos fuente:

/* archivo1.c */ 
int arr [ 10 ]; struct x { int uno ; int dos ;}; /* más código */  
     


/* file2.c */ 
extern int arr []; struct x ; /* más código */   
 

Ambos archivos son perfectamente legales en C, y el código en file1.c puede aplicar sizeof a arr y struct x . Sin embargo, es ilegal que el código en file2.c haga esto, porque las definiciones en file2.c no están completas. En el caso de arr , el código no especifica la dimensión de la matriz; sin esta información, el compilador no tiene forma de saber cuántos elementos hay en la matriz y no puede calcular el tamaño total de la matriz. Del mismo modo, el compilador no puede calcular el tamaño de struct x porque no sabe de qué miembros está compuesta y, por lo tanto, no puede calcular la suma de los tamaños de los miembros de la estructura (y el relleno). Si el programador proporcionara el tamaño de la matriz en su declaración en file2.c , o completara la definición de struct x proporcionando una lista de miembros, esto permitiría la aplicación de sizeof a arr o struct x en ese archivo fuente.

Miembros de objeto

C++11 introdujo la posibilidad de aplicar el parámetro sizeof a miembros específicos de una clase sin la necesidad de instanciar el objeto para lograr esto. [3] El siguiente ejemplo, por ejemplo, arroja4y8en la mayoría de las plataformas.

#include <flujo de datos> 

estructura foo { int a ; int b ; };  
   
   


int main () { std :: cout << tamaño de foo :: a << " \n " << tamaño de ( foo ) << " \n " ; }  

            

Paquetes de plantillas variadas

C++11 introdujo plantillas variádicas ; la palabra clave sizeof seguida de puntos suspensivos devuelve la cantidad de elementos en un paquete de parámetros.

plantilla < nombre_tipo ... Args > void print_size ( Args ... args ) { std :: cout << tamañode ... ( args ) << " \n " ; }  
   

       


int main () { print_size (); // genera 0 print_size ( "Es la respuesta" , 42 , verdadero ); // genera 3 }  

    
      

Implementación

Cuando se aplican a un tipo de datos o variable de longitud fija, las expresiones con el operador sizeof se evalúan durante la compilación del programa; se reemplazan por valores de resultado constantes. El estándar C99 introdujo matrices de longitud variable (VLA), que requerían la evaluación de dichas expresiones durante la ejecución del programa. En muchos casos, los detalles de implementación pueden documentarse en un documento de interfaz binaria de aplicación (ABI) para la plataforma, que especifica formatos, relleno y alineación para los tipos de datos, a los que debe ajustarse el compilador.

Relleno de estructura

Al calcular el tamaño de cualquier tipo de objeto, el compilador debe tener en cuenta cualquier alineación de estructura de datos requerida para cumplir con las restricciones de eficiencia o arquitectura. Muchas arquitecturas de computadora no admiten el acceso de múltiples bytes a partir de cualquier dirección de byte que no sea un múltiplo del tamaño de palabra, e incluso cuando la arquitectura lo permite, generalmente el procesador puede obtener un objeto alineado por palabra más rápido que un objeto que abarca varias palabras en la memoria. [4] Por lo tanto, los compiladores generalmente alinean las estructuras de datos al menos con un límite de palabra , y también alinean los miembros individuales con sus respectivos límites. En el siguiente ejemplo, es probable que la estructura student esté alineada con un límite de palabra, que también es donde comienza el miembro grade , y es probable que el miembro age comience en la siguiente dirección de palabra. El compilador logra esto último insertando bytes de relleno entre los miembros según sea necesario para satisfacer los requisitos de alineación. También puede haber relleno al final de una estructura para garantizar una alineación adecuada en caso de que la estructura se use como un elemento de una matriz.

Por lo tanto, el tamaño agregado de una estructura en C puede ser mayor que la suma de los tamaños de sus miembros individuales. Por ejemplo, en muchos sistemas el siguiente código imprime8:

struct student { char grade ; /* char tiene una longitud de 1 byte */ int age ; /* int tiene una longitud de 4 bytes */ };  
    
    


printf ( "%zu" , sizeof ( struct estudiante ));    

Véase también

Referencias

  1. ^ "Norma C99 (ISO/IEC9899)" (PDF) . ISO/IEC . 7 de septiembre de 2007. 6.5.3.4.3, pág. 80 . Consultado el 31 de octubre de 2010 .
  2. ^ "Borrador del Comité WG14/N1124 ISO/IEC 9899" (PDF) . 6 de mayo de 2005. 6 de mayo de 2005. 6.5.3.4 El operador sizeof .
  3. ^ "N2253 Extensión de sizeof para aplicar a miembros de datos no estáticos sin un objeto (Revisión 1)".
  4. ^ Rentzsch, Jonathan (8 de febrero de 2005). "Dataalignment: Straighten up and fly right" (Alineación de datos: enderezarse y volar correctamente). IBM . Consultado el 29 de septiembre de 2014 .
Obtenido de "https://es.wikipedia.org/w/index.php?title=Tamañode&oldid=1218719805"