stringtranslate.com

tipos de datos c

En el lenguaje de programación C , los tipos de datos constituyen la semántica y características de almacenamiento de elementos de datos. Se expresan en la sintaxis del lenguaje en forma de declaraciones de ubicaciones de memoria o variables . Los tipos de datos también determinan los tipos de operaciones o métodos de procesamiento de elementos de datos.

El lenguaje C proporciona tipos aritméticos básicos, como tipos de números enteros y reales , y sintaxis para crear tipos de matrices y compuestos. Los encabezados de la biblioteca estándar C , que se utilizarán mediante directivas de inclusión , contienen definiciones de tipos de soporte que tienen propiedades adicionales, como proporcionar almacenamiento con un tamaño exacto, independientemente de la implementación del lenguaje en plataformas de hardware específicas. [1] [2]

Tipos basicos

Tipos principales

El lenguaje C proporciona los cuatro especificadores de tipos aritméticos básicos char , int , float y double , y los modificadores signed , unsigned , short y long . La siguiente tabla enumera las combinaciones permitidas al especificar un gran conjunto de declaraciones específicas del tamaño de almacenamiento.

  1. ^ abcde Los rangos mínimos −(2 n −1 −1) a 2 n −1 −1 (por ejemplo, [−127,127]) provienen de las diversas representaciones de enteros permitidas por el estándar ( complemento a uno , signo-magnitud , complemento a dos ) . [4] Sin embargo, la mayoría de las plataformas utilizan el complemento a dos, lo que implica un rango de la forma −2 m −1 a 2 m −1 −1 con m  ≥  n para estas implementaciones, por ejemplo, [−128,127] ( SCHAR_MIN = −128 y SCHAR_MAX = 127) para un carácter firmado de 8 bits . Desde C23, la única representación permitida es el complemento a dos, por lo tanto los valores varían desde al menos −2 n −1 a 2 n −1 −1 . [5]
  2. ^ Estas cadenas de formato también existen para formatear texto, pero funcionan de forma doble.
  3. ^ ab Las mayúsculas difieren de las minúsculas en la salida. Los especificadores de mayúsculas producen valores en mayúsculas y minúsculas en minúsculas (%A, %E, %F, %G producen valores como INF, NAN y E (exponente) en mayúsculas)

El tamaño real de los tipos de números enteros varía según la implementación. El estándar solo requiere relaciones de tamaño entre los tipos de datos y tamaños mínimos para cada tipo de datos:

Los requisitos de la relación son que long longno sea menor que long, que no sea menor que int, que no sea menor que short. Como charel tamaño de es siempre el tipo de datos mínimo admitido, ningún otro tipo de datos (excepto los campos de bits ) puede ser menor.

El tamaño mínimo para chares de 8 bits, el tamaño mínimo para shorty intes de 16 bits, para longél es de 32 bits y long longdebe contener al menos 64 bits.

El tipo intdebe ser el tipo de número entero con el que el procesador de destino trabaja de manera más eficiente. Esto permite una gran flexibilidad: por ejemplo, todos los tipos pueden ser de 64 bits. Sin embargo, son populares varios esquemas diferentes de ancho de enteros (modelos de datos). Debido a que el modelo de datos define cómo se comunican los diferentes programas, se utiliza un modelo de datos uniforme dentro de una interfaz de aplicación de sistema operativo determinada. [9]

En la práctica, charsuele tener un tamaño de 8 bits y shortsuele tener un tamaño de 16 bits (al igual que sus homólogos sin signo). Esto es válido para plataformas tan diversas como SunOS  4 Unix de la década de 1990, Microsoft MS-DOS , Linux moderno y Microchip MCC18 para microcontroladores PIC integrados de 8 bits . POSIX requiere chartener exactamente 8 bits de tamaño. [10] [11]

Varias reglas en el estándar C hacen que unsigned charel tipo básico utilizado para matrices sea adecuado para almacenar objetos arbitrarios que no sean campos de bits: su falta de bits de relleno y representaciones trampa, la definición de representación de objetos , [7] y la posibilidad de alias. [12]

El tamaño real y el comportamiento de los tipos de punto flotante también varían según la implementación. El único requisito es que long doubleno sea menor que double, que no sea menor que float. Por lo general, se utilizan los formatos binarios de punto flotante IEEE 754 de 32 y 64 bits para floaty doublerespectivamente.

El estándar C99 incluye nuevos tipos de punto flotante real float_ty double_tdefinidos en <math.h>. Corresponden a los tipos utilizados para los resultados intermedios de expresiones de punto flotante cuando FLT_EVAL_METHODes 0, 1 o 2. Estos tipos pueden ser más anchos que long double.

C99 también agregó tipos complejosfloat _Complex : , double _Complex, long double _Complex. C11 añadió tipos imaginariosfloat _Imaginary (que fueron descritos en un anexo informativo de C99): , double _Imaginary, long double _Imaginary. Incluir el encabezado <complex.h>permite acceder a todos estos tipos usando complexy imaginaryrespectivamente.

tipo booleano

C99 agregó un tipo booleano (verdadero/falso) _Bool. Además, el <stdbool.h>encabezado define boolun alias conveniente para este tipo y también proporciona macros para truey false. _Boolfunciona de manera similar a un tipo entero normal, con una excepción: cualquier asignación a a _Boolque no sea 0 (falso) se almacena como 1 (verdadero). Este comportamiento existe para evitar desbordamientos de enteros en conversiones de restricción implícita. Por ejemplo, en el siguiente código:

carácter sin firmar b = 256 ;    si ( b ) { /* hacer algo */ }  

La variable bse evalúa como falsa si unsigned chartiene un tamaño de 8 bits. Esto se debe a que el valor 256 no encaja en el tipo de datos, lo que hace que se utilicen los 8 bits inferiores, lo que da como resultado un valor cero. Sin embargo, cambiar el tipo hace que el código anterior se comporte normalmente:

_Bool b = 256 ;   si ( b ) { /* hacer algo */ }  

El tipo _Bool también garantiza que los valores verdaderos siempre se comparen iguales entre sí:

_Bool a = 1 , b = 2 ;      if ( a == b ) { /* este código se ejecutará */ }    

Tipos de enteros con precisión de bits

Desde C23 , el lenguaje permite al programador definir números enteros que tienen un ancho de un número arbitrario de bits. Esos tipos se especifican como , donde N es una expresión constante entera que denota el número de bits, incluido el bit de signo para tipos con signo, representados en complemento a dos. El valor máximo de N lo proporciona y es al menos . Por lo tanto, el tipo (o ) toma valores de −2 a 1, mientras que toma valores de 0 a 3. El tipo también existe, siendo 0 o 1 y no tiene un tipo con signo equivalente. [13]_BitInt(N)BITINT_MAXWIDTHULLONG_WIDTH_BitInt(2)signed _BitInt(2)unsigned _BitInt(2)unsigned _BitInt(1)

Tipos de diferencia de tamaño y puntero

La especificación del lenguaje C incluye typedef sy para representar cantidades relacionadas con la memoria. Su tamaño se define según las capacidades aritméticas del procesador de destino, no las capacidades de memoria, como el espacio de direcciones disponible. Ambos tipos están definidos en el encabezado ( en C++).size_tptrdiff_t<stddef.h>cstddef

size_tes un tipo entero sin signo que se utiliza para representar el tamaño de cualquier objeto (incluidas las matrices) en una implementación particular. El operador sizeof produce un valor del tipo . El tamaño máximo de se proporciona mediante , una macro constante que se define en el encabezado ( encabezado en C++). Se garantiza que tendrá al menos 16 bits de ancho. Además, POSIX incluye , que es un tipo entero con signo del mismo ancho que .size_tsize_tSIZE_MAX<stdint.h>cstdintsize_tssize_tsize_t

ptrdiff_tes un tipo entero con signo que se utiliza para representar la diferencia entre punteros. Se garantiza que será válido sólo contra punteros del mismo tipo; La resta de punteros que constan de diferentes tipos está definida por la implementación.

Interfaz con las propiedades de los tipos básicos.

La información sobre las propiedades reales, como el tamaño, de los tipos aritméticos básicos, se proporciona a través de constantes macro en dos encabezados: <limits.h>encabezado ( climitsencabezado en C++) define macros para tipos enteros y <float.h>encabezado ( cfloatencabezado en C++) define macros para tipos de punto flotante . Los valores reales dependen de la implementación.

Propiedades de los tipos de números enteros

Propiedades de los tipos de punto flotante

Tipos de enteros de ancho fijo

El estándar C99 incluye definiciones de varios tipos enteros nuevos para mejorar la portabilidad de los programas. [2] Los tipos enteros básicos ya disponibles se consideraron insuficientes, porque sus tamaños reales están definidos por la implementación y pueden variar entre diferentes sistemas. Los nuevos tipos son especialmente útiles en entornos integrados donde el hardware normalmente solo admite varios tipos y ese soporte varía entre diferentes entornos. Todos los tipos nuevos se definen en <inttypes.h>el encabezado ( cinttypesencabezado en C++) y también están disponibles en <stdint.h>el encabezado ( cstdintencabezado en C++). Los tipos se pueden agrupar en las siguientes categorías:

La siguiente tabla resume los tipos y la interfaz para adquirir los detalles de implementación ( n se refiere al número de bits):

Especificadores de formato printf y scanf

El <inttypes.h>encabezado ( cinttypesen C++) proporciona características que mejoran la funcionalidad de los tipos definidos en el <stdint.h>encabezado. Define macros para los especificadores de cadenas de formato printf y scanf correspondientes a los tipos definidos en <stdint.h>y varias funciones para trabajar con los tipos intmax_ty uintmax_t. Este encabezado se agregó en C99 .

cadena de formato printf

Las macros están en formato . Aquí {fmt} define el formato de salida y es uno de (decimal), (hexadecimal), (octal), (sin signo) y (entero). {tipo} define el tipo de argumento y es uno de , , , , donde corresponde al número de bits del argumento.PRI{fmt}{type}dxouinFASTnLEASTnPTRMAXn

Cadena de formato scanf

Las macros están en formato . Aquí {fmt} define el formato de salida y es uno de (decimal), (hexadecimal), (octal), (sin signo) y (entero). {tipo} define el tipo de argumento y es uno de , , , , donde corresponde al número de bits del argumento.SCN{fmt}{type}dxouinFASTnLEASTnPTRMAXn

Funciones

Tipos de punto flotante adicionales

De manera similar a los tipos enteros de ancho fijo, ISO/IEC TS 18661 especifica tipos de punto flotante para intercambio IEEE 754 y formatos extendidos en binario y decimal:

Estructuras

Las estructuras agregan el almacenamiento de múltiples elementos de datos, de tipos de datos potencialmente diferentes, en un bloque de memoria al que hace referencia una única variable. El siguiente ejemplo declara el tipo de datos struct birthdayque contiene el nombre y la fecha de nacimiento de una persona. La definición de la estructura va seguida de una declaración de la variable Johnque asigna el almacenamiento necesario.

estructura cumpleaños { nombre char [ 20 ]; día entero ; mes entero ; año entero ; };      estructura cumpleaños John ;  

El diseño de la memoria de una estructura es una cuestión de implementación del lenguaje para cada plataforma, con algunas restricciones. La dirección de memoria del primer miembro debe ser la misma que la dirección de la estructura misma. Las estructuras se pueden inicializar o asignar para usar literales compuestos. Una función puede devolver directamente una estructura, aunque esto no suele ser eficiente en tiempo de ejecución. Desde C99 , una estructura también puede terminar con un miembro de matriz flexible .

Una estructura que contiene un puntero a una estructura de su propio tipo se usa comúnmente para construir estructuras de datos vinculados :

nodo de estructura { int val ; nodo de estructura * siguiente ; };     

matrices

Para cada tipo T, excepto los tipos void y function, existen los tipos "matriz de Nelementos de tipo T" . Una matriz es una colección de valores, todos del mismo tipo, almacenados de forma contigua en la memoria. Una matriz de tamaño Nestá indexada por números enteros desde 0hasta e inclusive N−1. Aquí hay un breve ejemplo:

int gato [ 10 ]; // matriz de 10 elementos, cada uno de tipo int  

Las matrices se pueden inicializar con un inicializador compuesto, pero no asignarse. Las matrices se pasan a funciones pasando un puntero al primer elemento. Las matrices multidimensionales se definen como "matriz de matriz..." y todas, excepto la dimensión más externa, deben tener un tamaño constante en tiempo de compilación:

int a [ 10 ][ 8 ]; // matriz de 10 elementos, cada uno de tipo 'matriz de 8 elementos int'  

Consejos

Cada tipo de datos Ttiene un punteroT de tipo correspondiente . Un puntero es un tipo de datos que contiene la dirección de una ubicación de almacenamiento de una variable de un tipo particular. Se declaran con el *declarador de tipo asterisco ( ) después del tipo de almacenamiento básico y antes del nombre de la variable. Los espacios en blanco antes o después del asterisco son opcionales.

carácter * cuadrado ; círculo largo * ; int * óvalo ;   

También se pueden declarar punteros para tipos de datos de puntero, creando así múltiples punteros indirectos, como char ** e int *** , incluidos punteros a tipos de matriz. Estos últimos son menos comunes que una serie de punteros y su sintaxis puede resultar confusa:

carbón * ordenador personal [ 10 ]; // matriz de 10 elementos de 'puntero a char' char ( * pa )[ 10 ]; // puntero a una matriz de 10 elementos de caracteres    

El elemento pcrequiere diez bloques de memoria del tamaño de un punterochar (generalmente 40 u 80 bytes en plataformas comunes), pero el elemento paes solo un puntero (tamaño 4 u 8 bytes) y los datos a los que se refiere son una matriz de diez bytes. ( ).sizeof *pa == 10

Sindicatos

Un tipo de unión es una construcción especial que permite el acceso al mismo bloque de memoria mediante una selección de descripciones de tipos diferentes. Por ejemplo, se puede declarar una unión de tipos de datos para permitir leer los mismos datos ya sea como un número entero, un flotante o cualquier otro tipo declarado por el usuario:

unión { int i ; flotar f ; estructura { unsigned int u ; doble d ; } s ; } tu ;         

El tamaño total de ues el tamaño de u.s– que resulta ser la suma de los tamaños de u.s.uy u.s.d– ya que ses mayor que ambos iy f. Al asignar algo a , es posible que se conserven u.ialgunas partes de si es más pequeño que .u.fu.iu.f

Leer de un miembro del sindicato no es lo mismo que emitir, ya que el valor del miembro no se convierte, sino que simplemente se lee.

Punteros de función

Los punteros de función permiten hacer referencia a funciones con una firma particular. Por ejemplo, para almacenar la dirección de la función estándar absen la variable my_int_f:

int ( * my_int_f )( int ) = & abs ; // el operador & se puede omitir, pero deja claro que aquí se utiliza la "dirección de" abs   

Los punteros a funciones se invocan por su nombre al igual que las llamadas a funciones normales. Los punteros de función están separados de los punteros y de los punteros nulos .

Calificadores de tipo

Los tipos antes mencionados se pueden caracterizar aún más mediante calificadores de tipo , lo que produce un tipo calificado . A partir de 2014 y C11 , hay cuatro calificadores de tipo en el estándar C: const( C89 ), volatile( C89 ), restrict( C99 ) y _Atomic( C11 ); este último tiene un nombre privado para evitar conflictos con los nombres de usuario, [14] pero el más atomicSe puede utilizar un nombre normal si <stdatomic.h>se incluye el encabezado. De estos, constes, con diferencia, el más conocido y utilizado, aparece en la biblioteca estándar y se encuentra en cualquier uso significativo del lenguaje C, que debe satisfacer la corrección constante . Los otros calificadores se utilizan para programación de bajo nivel y, aunque se utilizan ampliamente allí, los programadores típicos rara vez los utilizan. [ cita necesaria ]

Ver también

Referencias

  1. ^ Barr, Michael (2 de diciembre de 2007). "Enteros portátiles de ancho fijo en C" . Consultado el 18 de enero de 2016 .
  2. ^ ab Especificación ISO/IEC 9899:1999, TC3 (PDF) . pag. 255, § 7.18 Tipos de enteros <stdint.h> .
  3. ^ abcdefghij Especificación ISO/IEC 9899:1999, TC3 (PDF) . pag. 22, § 5.2.4.2.1 Tamaños de tipos de enteros <limits.h> .
  4. ^ Justificación del estándar internacional: lenguajes de programación: revisión C 5.10 (PDF) . pag. 25, § 5.2.4.2.1 Tamaños de tipos de enteros <limits.h> .
  5. ^ Borrador de especificación ISO/IEC 9899:2023 (PDF) . pag. 41, § 6.2.6 Representaciones de tipos .
  6. ^ "Límites de enteros de C y C++". 21 de julio de 2023.
  7. ^ ab Especificación ISO/IEC 9899:1999, TC3 (PDF) . pag. 37, § 6.2.6.1 Representaciones de tipos – Generalidades .
  8. ^ Especificación abcdef ISO/IEC 9899:1999, TC3 (PDF) . pag. 56, § 6.4.4.1 Constantes enteras .
  9. ^ "Modelos de programación de 64 bits: ¿Por qué LP64?". El grupo abierto . Consultado el 9 de noviembre de 2011 .
  10. ^ "Ancho de tipo (la biblioteca GNU C)". www.gnu.org . Consultado el 30 de julio de 2022 .
  11. ^ "<límites.h>". pubs.opengroup.org . Consultado el 30 de julio de 2022 .
  12. ^ Especificación ISO/IEC 9899:1999, TC3 (PDF) . pag. 67, § 6.5 Expresiones .
  13. ^ Borrador de especificación ISO/IEC 9899:2023 (PDF) . pag. 37, § 6.2.5 Tipos .
  14. ^ C11: El nuevo estándar C, Thomas Plum