Articulo de referencia

Tipos de datos de C

En el lenguaje de programación C , los tipos de datos constituyen la semántica y las características de almacenamiento de los elementos de datos. Se expresan en la sintaxis del ...

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

El lenguaje C proporciona tipos aritméticos básicos, como enteros y números reales , y sintaxis para construir matrices y tipos compuestos. La biblioteca estándar de C contiene definiciones adicionales de tipos de soporte, que poseen 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 primarios

Tipos principales

El lenguaje C proporciona los cuatro especificadores de tipo aritmético básicos char, int, floaty double(así como el tipo booleano bool), y los modificadores signed, unsigned, short, y long. La siguiente tabla enumera las combinaciones permitidas para especificar un gran conjunto de declaraciones específicas del tamaño de almacenamiento.

  1. El término estándar para el tamaño de un tipo entero en bits es ancho . El ancho no incluye bits de relleno.
  2. 1 2 3 4 5 Los rangos mínimos [ −(2 n −1 −1), 2 n −1 −1 ] (por ejemplo, [−127,127]) provienen de las diversas representaciones enteras permitidas por el estándar ( complemento a uno , magnitud de signo , complemento a dos ). [ 5 ] Sin embargo, la mayoría de las plataformas usan complemento a dos, lo que implica un rango de la forma [ −2 m −1 , 2 m −1 −1 ] con mn para estas implementaciones, por ejemplo, [−128,127] (y ) para un carácter con signo 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 , 2 n −1 −1 ] . [ 6 ]SCHAR_MIN == −128SCHAR_MAX == 127
  3. o%hhipara salida numérica
  4. o%hhupara salida numérica
  5. Estas cadenas de formato también existen para dar formato al texto, pero operan sobre un doble.
  6. 1 2 Las mayúsculas difieren de las minúsculas en la salida. Los especificadores de mayúsculas producen valores en mayúsculas, y los de 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 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 dato:

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 dato mínimo admitido, ningún otro tipo de dato (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 longes de 32 bits y long longdebe contener al menos 64 bits.

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

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 contrapartes sin signo). Esto se cumple 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 charque tenga exactamente un tamaño de 8 bits. [ 11 ] [ 12 ]

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

El tamaño y el comportamiento reales 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 a su vez no es menor que . Por lo general, se utilizan los formatos binarios de punto flotante IEEE 754float de 32 bits y 64 bits para y respectivamente.floatdouble

El estándar C99 incluye nuevos tipos de punto flotante reales float_ty double_t, definidos 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 amplios que long double.

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

Tipo booleano

C99 añadió un tipo de datos booleano_Bool . Además, el <stdbool.h>encabezado define boolcomo un 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 conversión a _Boolda 0 (falso) si el valor es igual a 0; de lo contrario, da 1 (verdadero). Este comportamiento existe para evitar desbordamientos de enteros en conversiones de estrechamiento implícitas. Por ejemplo, en el siguiente código:

unsigned char 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 cabe en el tipo de dato, lo que provoca que se utilicen los 8 bits inferiores, resultando en un valor cero. Sin embargo, al cambiar el tipo, el código anterior se comporta con normalidad.

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

Este tipo _Booltambién garantiza que los valores verdaderos siempre sean iguales entre sí:

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

En C23 , bool(y sus valores truey false) se convirtió en una funcionalidad central del lenguaje (haciendo que el contenido de <stdbool.h>quedara obsoleto [ 14 ] [ 15 ] ), lo que permitió los siguientes ejemplos de código:

bool b = verdadero ;if ( b ) { // este código se ejecutará }

Tipos de enteros con precisión de bits

Desde C23 , el lenguaje permite al programador definir enteros con un ancho de un número arbitrario de bits. Estos tipos se especifican como , donde N es una expresión constante entera que denota el número de bits, incluyendo el bit de signo para los tipos con signo, representados en complemento a dos. El valor máximo de N viene dado por 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. [ 16 ] Una propuesta para C2Y propone eliminar esta restricción y permitir , que entonces tiene los posibles valores 0 y -1, eliminando el caso especial para . [ 17 ]_BitInt(N)BITINT_MAXWIDTHULLONG_WIDTH_BitInt(2)signed_BitInt(2)unsigned_BitInt(2)unsigned_BitInt(1)signed_BitInt(1)unsigned_BitInt(1)

Tipos de diferencia de tamaño y puntero

La especificación del lenguaje C incluye los tipos `typedef` y `reg` para representar cantidades relacionadas con la memoria. Su tamaño se define según las capacidades aritméticas del procesador de destino, no según las capacidades de memoria, como el espacio de direcciones disponible. Ambos tipos se definen en el archivo de cabecera.size_tptrdiff_t<stddef.h>

size_tes un tipo entero sin signo que se utiliza para representar el tamaño de cualquier objeto (incluidos los arreglos) en la implementación particular. El operador sizeof produce un valor del tipo . El tamaño máximo de se proporciona a través de , una constante macro que se define en el encabezado. 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>size_tssize_tsize_t

ptrdiff_tes un tipo de entero con signo que se utiliza para representar la diferencia entre punteros. Se garantiza su validez únicamente con punteros del mismo tipo; la resta de punteros de tipos diferentes depende de la implementación.

Interfaz para 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 mediante constantes macro en dos archivos de cabecera: <limits.h>uno define las macros para los tipos enteros y <float.h>otro para los tipos de coma flotante. Los valores reales dependen de la implementación.

Propiedades de los tipos enteros

  • CHAR_BIT– tamaño del tipo de carácter en bits, comúnmente denominado tamaño de un byte (al menos 8 bits)
  • SCHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN(C99) – valor mínimo posible de los tipos enteros con signo: signed char, signed short, signed int, signed long, signed long long
  • SCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX(C99) – valor máximo posible de los tipos enteros con signo: signed char, signed short, signed int, signed long, signed long long
  • UCHAR_MAX, USHRT_MAX, UINT_MAX, ULONG_MAX, ULLONG_MAX(C99) – valor máximo posible de los tipos enteros sin signo: unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long
  • CHAR_MIN– valor mínimo posible de char
  • CHAR_MAX– valor máximo posible de char
  • MB_LEN_MAX– número máximo de bytes en un carácter multibyte
  • BOOL_WIDTH(C23) - ancho de bits de _Bool, siempre 1
  • CHAR_WIDTH(C23) - ancho de bits de char; CHAR_WIDTH, UCHAR_WIDTHy SCHAR_WIDTHson iguales CHAR_BITpor definición
  • SCHAR_WIDTH, SHRT_WIDTH, INT_WIDTH, LONG_WIDTH, LLONG_WIDTH(C23) - ancho de bits de signed char, short, int, long, y long longrespectivamente
  • UCHAR_WIDTH, USHRT_WIDTH, UINT_WIDTH, ULONG_WIDTH, ULLONG_WIDTH(C23) - ancho de bits de unsigned char, unsigned short, unsigned int, unsigned long, y unsigned long longrespectivamente

Propiedades de los tipos de punto flotante

  • FLT_MIN, DBL_MIN, LDBL_MIN– valor positivo normalizado mínimo de float, double, long double respectivamente
  • FLT_TRUE_MIN, DBL_TRUE_MIN, LDBL_TRUE_MIN(C11) – valor positivo mínimo de float, double, long double respectivamente
  • FLT_MAX, DBL_MAX, LDBL_MAX– valor finito máximo de float, double, long double, respectivamente
  • FLT_ROUNDS– modo de redondeo para operaciones de punto flotante
  • FLT_EVAL_METHOD(C99) – método de evaluación de expresiones que involucran diferentes tipos de punto flotante
  • FLT_RADIX– raíz del exponente en los tipos de punto flotante
  • FLT_DIG, DBL_DIG, LDBL_DIG– número de dígitos decimales que pueden representarse sin perder precisión mediante float, double y long double, respectivamente.
  • FLT_EPSILON, DBL_EPSILON, LDBL_EPSILONdiferencia entre 1.0 y el siguiente valor representable de float, double, long double, respectivamente
  • FLT_MANT_DIG, DBL_MANT_DIG, LDBL_MANT_DIG– número de FLT_RADIXdígitos en base - en la mantisa de punto flotante para los tipos float, double, long double, respectivamente
  • FLT_MIN_EXP, DBL_MIN_EXP, LDBL_MIN_EXP– entero negativo mínimo tal que FLT_RADIXelevado a una potencia uno menor que ese número es un float, double y long double normalizados, respectivamente.
  • FLT_MIN_10_EXP, DBL_MIN_10_EXP, LDBL_MIN_10_EXP– entero negativo mínimo tal que 10 elevado a esa potencia es un float, double y long double normalizados, respectivamente.
  • FLT_MAX_EXP, DBL_MAX_EXP, LDBL_MAX_EXP– máximo entero positivo tal que FLT_RADIXelevado a una potencia uno menor que ese número es un float, double y long double normalizados, respectivamente.
  • FLT_MAX_10_EXP, DBL_MAX_10_EXP, LDBL_MAX_10_EXP– máximo entero positivo tal que 10 elevado a esa potencia es un float, double y long double normalizados, respectivamente.
  • DECIMAL_DIG(C99) – número mínimo de dígitos decimales tal que cualquier número del tipo de punto flotante más amplio admitido se puede representar en decimal con una precisión de DECIMAL_DIGdígitos y leerse de nuevo en el tipo de punto flotante original sin cambiar su valor. DECIMAL_DIGes al menos 10.

Tipos enteros de ancho fijo

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

  • Tipos de enteros de ancho exacto que garantizan tener el mismo número n de bits en todas las implementaciones. Se incluyen solo si están disponibles en la implementación.
  • Tipos enteros de ancho mínimo que garantizan ser el tipo más pequeño disponible en la implementación, con al menos el número especificado n de bits. Se garantiza que se especifique para al menos N=8, 16, 32, 64.
  • Tipos de enteros más rápidos que garantizan ser los más rápidos disponibles en la implementación, con al menos el número especificado n de bits. Se garantiza que se especifique para al menos N=8, 16, 32, 64.
  • Tipos de enteros puntero que garantizan la capacidad de almacenar un puntero. Se incluyen solo si están disponibles en la implementación.
  • Tipos de enteros de ancho máximo que garantizan ser el tipo de entero más grande en la implementación.

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

Especificadores de formato de printf y scanf

El <inttypes.h>encabezado proporciona características que mejoran la funcionalidad de los tipos definidos en el <stdint.h>encabezado. Define macros para los especificadores de cadena 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 tienen el formato . Aquí {fmt} define el formato de salida y es uno de (decimal), (hexadecimal), (octal), (sin signo) y (entero). {type} define el tipo del argumento y es uno de , , , , , donde corresponde al número de bits del argumento.PRI{fmt}{type}dxouinFASTnLEASTnPTRMAXn

cadena de formato scanf

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

Funciones

Tipos de coma flotante adicionales

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

  • _FloatNpara formatos de intercambio binario;
  • _DecimalNpara formatos de intercambio decimal;
  • _FloatNxpara formatos binarios extendidos;
  • _DecimalNxpara formatos decimales extendidos.

Consejos

Cada tipo de dato Ttiene un punteroT de tipo correspondiente . Un puntero es un tipo de dato que contiene la dirección de una ubicación de almacenamiento de una variable de un tipo específico. Se declaran con el 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.

char * p ; long * q ; int * r ;

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

char * pc [ 10 ]; // matriz de 10 elementos de 'puntero a char' char ( * pa )[ 10 ]; // puntero a una matriz de 10 elementos de char

El elemento pcrequiere diez bloques de memoria del tamaño de un punterochar (normalmente 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

C también tiene un "puntero a void", void *. [ 18 ] El nombre "puntero a void" no implica que apunte a voidmemoria (ya que voides un tipo incompleto sin tamaño), sino que apunta a algo de tipo no especificado. Debe convertirse a otro tipo de puntero antes de poder ser desreferenciado. Un void *no puede apuntar a una función. Una llamada a mallocdevuelve void *, y freetoma un void *.

C utiliza el concepto de puntero nulo para denotar un puntero que no se refiere a ningún dato válido. La macro NULLse usa a menudo en lugar de un puntero nulo, confiando en la conversión de tipo implícita cuando es posible. Sin embargo, este uso puede ser problemático y puede ser una fuente de errores de programación. En particular, la expansión de NULLpuede tener un tipo de puntero o un tipo entero, dependiendo de la implementación. C23 introdujo la constante predefinida nullptry su tipo nullptr_t(que tiene el único valor nullptr) para expresar una constante de puntero nulo. nullptres inequívocamente un puntero, y puede convertirse en cualquier puntero de objeto o función, y permite un nullptr_tcaso específico en _Generic. [ 19 ] El tamaño y la alineación de este tipo son los mismos que para un puntero al tipo carácter (o void *), pero otros tipos de puntero aún pueden tener un tamaño y una alineación diferentes; por lo tanto, no todos los punteros nulos son reemplazables con nullptr. [ 20 ]

Matrices

Para cada tipo T, excepto los tipos void y de función, existen los tipos "array de Nelementos de tipo T" . Un array es una colección de valores, todos del mismo tipo, almacenados de forma contigua en la memoria. Un array de tamaño Nse indexa mediante enteros desde 0hasta inclusive N − 1. He aquí un breve ejemplo:

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

Los arreglos se pueden inicializar con un inicializador compuesto, pero no se les puede asignar un valor. Los arreglos se pasan a las funciones mediante un puntero al primer elemento. Los arreglos multidimensionales se definen como "arreglo de arreglos..." , y todas las dimensiones, excepto la más externa, deben tener un tamaño constante en tiempo de compilación:

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

En C, una cadena a menudo se almacena como una matriz de char( char[]), pero esto es distinto de un puntero a char( char *). char[]no se puede reasignar y permanece donde se define, mientras que char *es reasignable, pero no se puede modificar.

char s [] = "¡Hola, mundo!" ; char * p = s ; // s se convierte en &s[0], p apunta al primer carácter

Incluso si una función toma T[]como parámetro, se convierte en un T *que apunta a su primer elemento.

void f ( int a []);// esto es lo mismo que: void f ( int * a );

La indexación de un array se define en términos de aritmética de punteros , es decir, a[i]es equivalente a *(a + i). [ 21 ]

Enumeraciones

En C, un enum es un tipo entero cuyos valores están restringidos a un conjunto de constantes con nombre. [ 22 ] Los enums no se pueden declarar anticipadamente. También se les pueden asignar valores directamente y se utilizan comúnmente switchpara enumerar múltiples casos.

#include <stddef.h>enum Estado { OK = 200 , NO_ENCONTRADO = 404 , ERROR_SERVIDOR = 500 };const char * get_status_string ( enum Status status ) { switch ( status ) { case OK : return "Éxito" ; case NOT_FOUND : return "No encontrado" ; case SERVER_ERROR : return "Error del servidor" ; default : unreachable (); } }

Las constantes de enumeración se conocen en tiempo de compilación y suelen ser una forma más segura de definir constantes enteras que las macros. El tamaño subyacente de una enumeración suele ser int, pero desde C23 se puede especificar directamente que el tamaño subyacente de una enumeración sea de cualquier tipo entero.

enum Color : char { ROJO = 1 , NARANJA , AMARILLO , VERDE , AZUL , ÍNDIGO , VIOLETA };

Dado que las enumeraciones no son de tipo seguro, se les puede asignar un valor de otra enumeración. Además, no es necesario que los valores asignados a las enumeraciones estén necesariamente dentro del rango de valores definidos.

enum Color color = AMARILLO ; // AMARILLO = 3 enum Month month = JUNIO ; // JUNIO = 6color = mes ; // el color ahora es 6 (ÍNDIGO) mes = 999 ; // puede que no haya un valor de 999 en el enumerador Mes, pero aún así está permitido

Estructuras

Las estructuras (structs) agrupan el almacenamiento de múltiples elementos de datos, de tipos potencialmente diferentes, en un bloque de memoria contiguo al que hace referencia una única variable. Es posible que los miembros se rellenen para alinear la memoria , por lo que a menudo se recomienda ordenar los campos de mayor a menor tamaño para un uso eficiente de la memoria.

struct Student { char name [ 50 ]; unsigned int id ; unsigned int semester ; float gpa ; };// Inicialización posicional: los valores coinciden con el orden de los campos struct Student alice = { " Alice" , 123 , 2 , 3.8 } ; // Inicializador designado (desde C99) struct Student bob = { .name = "Bob" , .id = 246 , .semestre = 1 , .gpa = 3.9 } ;

Las estructuras también pueden usar campos de bits para permitir que los campos compartan las mismas unidades de almacenamiento, pero la disposición de los elementos depende de la implementación.

struct Properties { // tres campos se pueden empaquetar de forma compacta en un byte unsigned char visible : 1 ; // a ocupa 1 bit unsigned char color : 3 ; // b ocupa 3 bits unsigned char size : 4 ; // c ocupa 4 bits };

La disposición en memoria de una estructura es un problema 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 pueden inicializarse o asignarse mediante literales compuestos. Una función puede devolver directamente una estructura, aunque esto a menudo no es eficiente en tiempo de ejecución. Desde C99 , una estructura también puede terminar con un miembro de matriz flexible .

Las funciones pueden recibir una estructura como parámetro por valor, pero esto resulta costoso, ya que copia la estructura completa. Por otro lado, suele ser preferible pasarla por puntero, puesto que se conoce el tamaño de un puntero (normalmente 4 u 8 bytes).

#include <stdio.h>// Pasar por valor void print_student ( struct Student s ) { printf ( "Nombre: %s, ID: %d, en semestre %d, con promedio: %.2f \n " , s . name , s . id , s . semester , s . gpa ); }// paso por puntero void print_student ( struct Student * s ) { printf ( "Nombre: %s, ID: %d, en semestre %d, con promedio: %.2f \n " , s -> nombre , s -> id , s -> semestre , s -> promedio ); }

Las estructuras pueden estar compuestas por otras estructuras:

struct Fecha { int año ; int mes ; int día ; };struct Birthday { char name [ 50 ]; struct Date dob ; };

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

struct LinkedList { void * item ; // almacena el elemento actual struct LinkedList * next ; // almacena la siguiente lista, o NULL si no hay nada siguiente };

sindicatos

Un tipo de unión es una construcción especial que permite acceder al mismo bloque de memoria mediante la elección de diferentes descripciones de tipo.

// contiene un valor entero o de punto flotante union Number { int i ; float f ; } d ;d . i = 10 ; // d ahora contiene 10 d . f = 3.14f ; // d ahora contiene 3.14, sobrescribiendo 10

En el siguiente ejemplo, se puede declarar una unión de tipos de datos para permitir la lectura de los mismos datos como un entero, un número de coma flotante o cualquier otro tipo declarado por el usuario:

unión { int i ; float f ; struct { unsigned int u ; double d ; } s ; } u ;

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 u.i, algunas partes de u.fpueden conservarse si u.ies menor que u.f.

Leer un miembro de una unión no es lo mismo que realizar una operación de conversión, ya que el valor del miembro no se convierte, sino que simplemente se lee.

Punteros a funciones

Los punteros a funciones 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 & puede omitirse, 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.

#include <stdio.h> #include <stdlib.h>int ( * my_abs )( int ) = & abs ; int x = -42 ; int abs_of_x = my_abs ( x ); printf ( "abs(%d) = %d \n " , x , abs_of_x );

Calificadores de tipo

Los tipos mencionados anteriormente pueden caracterizarse aún más mediante calificadores de tipo , lo que da como resultado un tipo calificado . A partir de 2014y C11 , hay cuatro calificadores de tipo en C estándar:

  • const( C89 )
  • volatile( C89 )
  • restrict( C99 )
  • _Atomic( C11 ) este último tiene un nombre privado para evitar conflictos con los nombres de usuario, [ 23 ] pero se puede usar el nombre más común si se incluye el encabezado. atomic<stdatomic.h>

De estos, constes de lejos el más conocido y utilizado , que aparece en la biblioteca estándar de C y se encuentra en cualquier uso significativo del lenguaje C, que debe satisfacer la corrección constante . Los otros calificadores se utilizan principalmente para la programación de bajo nivel: tiene como objetivo suprimir las optimizaciones del compilador en una variable al sugerir que puede cambiar en cualquier momento, indica que el objeto al que apunta un puntero es accedido solo por ese puntero, e indica que el objeto es "atómico", es decir, las lecturas y escrituras son indivisibles.volatilerestrict_Atomic

Véase también

Referencias

  1. Barr, Michael (2 de diciembre de 2007). "Enteros portátiles de ancho fijo en C" . Recuperado el 18 de enero de 2016 .
  2. 1 2 Especificación ISO/IEC 9899:1999, TC3 (PDF) . pág. 255, § 7.18 Tipos enteros <stdint.h> .
  3. "Tipos aritméticos" . cppreference.com . Consultado el 15 de septiembre de 2025 .
  4. 1 2 3 4 5 6 7 8 9 10 Especificación ISO/IEC 9899:1999, TC3 (PDF) . pág. 22, § 5.2.4.2.1 Tamaños de tipos enteros <limits.h> .
  5. Fundamento de la norma internacional: lenguajes de programación: C, revisión 5.10 (PDF) . pág. 25, § 5.2.4.2.1 Tamaños de tipos enteros <limits.h> .
  6. Borrador de la especificación ISO/IEC 9899:2023 (PDF) . pág. 41, § 6.2.6 Representaciones de tipos .
  7. "Límites de enteros en C y C++" . 21 de julio de 2023.
  8. 1 2 Especificación ISO/IEC 9899:1999, TC3 (PDF) . pág. 37, § 6.2.6.1 Representaciones de tipos – General .
  9. 1 2 3 4 5 6 Especificación ISO/IEC 9899:1999, TC3 (PDF) . pág. 56, § 6.4.4.1 Constantes enteras .
  10. "Modelos de programación de 64 bits: ¿Por qué LP64?" . The Open Group . Consultado el 9 de noviembre de 2011 .
  11. "Ancho de tipo (La biblioteca C de GNU)" . www.gnu.org . Consultado el 30 de julio de 2022 .
  12. "<limits.h>" . pubs.opengroup.org . Consultado el 30 de julio de 2022 .
  13. Especificación ISO/IEC 9899:1999, TC3 (PDF) . pág. 67, § 6.5 Expresiones .
  14. IEEE y The Open Group (2024). "<stdbool.h>" . pubs.opengroup.org . IEEE Std 1003.1-2024.
  15. cppreference.com. "Encabezado de la biblioteca estándar <stdbool.h>" . cppreference.com . cppreference.com . Consultado el 7 de febrero de 2026 .
  16. Borrador de la especificación ISO/IEC 9899:2023 (PDF) . pág. 37, § 6.2.5 Tipos .
  17. Conjuntos de enteros, v3, WG14 N 3699 . p. 6, § 1.2 Enteros con precisión de bits .
  18. Especificación ISO/IEC 9899:1999, TC3 (PDF) . pág. 47, § 6.3.2.3 Punteros .
  19. cppreference.com. "nullptr_t" . cppreference.com . cppreference.com . Consultado el 7 de febrero de 2026 .
  20. "WR14-N3042: Introducir la constante nullptr" . open-std.org . 22 de julio de 2022. Archivado del original el 24 de diciembre de 2022.
  21. Plauger, PJ ; Brodie , Jim (1992). ANSI and ISO Standard C Programmer's Reference . Redmond, WA: Microsoft Press. p. 108. ISBN  978-1-55615-359-4.
  22. cppreference.com. "Enumeraciones" . cppreference.com . cppreference.com . Consultado el 7 de febrero de 2026 .
  23. C11: El nuevo estándar C , Thomas Plum
Obtenido de " https://en.wikipedia.org/w/index.php?title=C_data_types&oldid=1361609861 "