C Language
Tipos de datos
Buscar..
Observaciones
- Aunque se requiere que
char
sea de 1 byte, no se requiere que 1 byte sea de 8 bits (a menudo también se denomina octeto ), aunque la mayoría de las plataformas de computadoras modernas lo definen como 8 bits. El número de bits de la implementación porchar
lo proporciona la macroCHAR_BIT
, definida en<limits.h>
. POSIX requiere 1 byte para ser de 8 bits. - Los tipos de enteros de ancho fijo deben usarse de forma dispersa, los tipos incorporados de C están diseñados para ser naturales en cada arquitectura, los tipos de ancho fijo solo deben usarse si necesita explícitamente un entero de tamaño específico (por ejemplo, para redes).
Tipos enteros y constantes
Los enteros con signo pueden ser de estos tipos ( int
después de short
o long
es opcional):
signed char c = 127; /* required to be 1 byte, see remarks for further information. */
signed short int si = 32767; /* required to be at least 16 bits. */
signed int i = 32767; /* required to be at least 16 bits */
signed long int li = 2147483647; /* required to be at least 32 bits. */
signed long long int li = 2147483647; /* required to be at least 64 bits */
Cada uno de estos tipos de enteros con signo tiene una versión sin firmar.
unsigned int i = 65535;
unsigned short = 2767;
unsigned char = 255;
Para todos los tipos, excepto char
se asume la versión signed
si se omite la parte signed
o unsigned
. El tipo char
constituye un tercer tipo de carácter, diferente del signed char
y unsigned char
y la firma (o no) depende de la plataforma.
Se pueden escribir diferentes tipos de constantes enteras (llamadas literales en la jerga C) en diferentes bases y diferentes anchos, según su prefijo o sufijo.
/* the following variables are initialized to the same value: */
int d = 42; /* decimal constant (base10) */
int o = 052; /* octal constant (base8) */
int x = 0xaf; /* hexadecimal constants (base16) */
int X = 0XAf; /* (letters 'a' through 'f' (case insensitive) represent 10 through 15) */
Las constantes decimales siempre están signed
. Las constantes hexadecimales comienzan con 0x
o 0X
y las constantes octales comienzan con 0
. Los dos últimos están signed
o unsigned
según si el valor se ajusta al tipo firmado o no.
/* suffixes to describe width and signedness : */
long int i = 0x32; /* no suffix represent int, or long int */
unsigned int ui = 65535u; /* u or U represent unsigned int, or long int */
long int li = 65536l; /* l or L represent long int */
Sin un sufijo, la constante tiene el primer tipo que se ajusta a su valor, es decir, una constante decimal que es más grande que INT_MAX
es de tipo long
si es posible, o long long
contrario.
El archivo de encabezado <limits.h>
describe los límites de los enteros de la siguiente manera. Sus valores definidos por la implementación serán iguales o mayores en magnitud (valor absoluto) a los que se muestran a continuación, con el mismo signo.
Macro | Tipo | Valor |
---|---|---|
CHAR_BIT | Objeto más pequeño que no es un campo de bits (byte) | 8 |
SCHAR_MIN | signed char | -127 / - (2 7 - 1) |
SCHAR_MAX | signed char | +127 / 2 7 - 1 |
UCHAR_MAX | unsigned char | 255/2 8 - 1 |
CHAR_MIN | char | vea abajo |
CHAR_MAX | char | vea abajo |
SHRT_MIN | short int | -32767 / - (2 15 - 1) |
SHRT_MAX | short int | +32767 / 2 15 - 1 |
USHRT_MAX | unsigned short int | 65535/2 16 - 1 |
INT_MIN | int | -32767 / - (2 15 - 1) |
INT_MAX | int | +32767 / 2 15 - 1 |
UINT_MAX | unsigned int | 65535/2 16 - 1 |
LONG_MIN | long int | -2147483647 / - (2 31 - 1) |
LONG_MAX | long int | +2147483647 / 2 31 - 1 |
ULONG_MAX | unsigned long int | 4294967295/2 32 - 1 |
Macro | Tipo | Valor |
---|---|---|
LLONG_MIN | long long int | -9223372036854775807 / - (2 63 - 1) |
LLONG_MAX | long long int | +9223372036854775807 / 2 63 - 1 |
ULLONG_MAX | unsigned long long int | 18446744073709551615/2 64 - 1 |
Si el valor de un objeto de tipo char
-se extiende cuando se usa en una expresión, el valor de CHAR_MIN
será el mismo que el de SCHAR_MIN
y el valor de CHAR_MAX
será el mismo que el de SCHAR_MAX
. Si el valor de un objeto de tipo char
no se extiende al signo cuando se usa en una expresión, el valor de CHAR_MIN
será 0 y el valor de CHAR_MAX
será el mismo que el de UCHAR_MAX
.
El estándar C99 agregó un nuevo encabezado, <stdint.h>
, que contiene definiciones para enteros de ancho fijo. Consulte el ejemplo de entero de ancho fijo para obtener una explicación más detallada.
Literales de cuerda
Un literal de cadena en C es una secuencia de caracteres, terminada por un cero literal.
char* str = "hello, world"; /* string literal */
/* string literals can be used to initialize arrays */
char a1[] = "abc"; /* a1 is char[4] holding {'a','b','c','\0'} */
char a2[4] = "abc"; /* same as a1 */
char a3[3] = "abc"; /* a1 is char[3] holding {'a','b','c'}, missing the '\0' */
Los literales de cadena no son modificables (y, de hecho, se pueden colocar en la memoria de solo lectura, como .rodata). Intentar alterar sus valores resulta en un comportamiento indefinido.
char* s = "foobar";
s[0] = 'F'; /* undefined behaviour */
/* it's good practice to denote string literals as such, by using `const` */
char const* s1 = "foobar";
s1[0] = 'F'; /* compiler error! */
Varios literales de cadena se concatenan en tiempo de compilación, lo que significa que puede escribir construcciones como éstas.
/* only two narrow or two wide string literals may be concatenated */
char* s = "Hello, " "World";
/* since C99, more than two can be concatenated */
/* concatenation is implementation defined */
char* s1 = "Hello" ", " "World";
/* common usages are concatenations of format strings */
char* fmt = "%" PRId16; /* PRId16 macro since C99 */
Los literales de cadena, al igual que las constantes de caracteres, admiten diferentes conjuntos de caracteres.
/* normal string literal, of type char[] */
char* s1 = "abc";
/* wide character string literal, of type wchar_t[] */
wchar_t* s2 = L"abc";
/* UTF-8 string literal, of type char[] */
char* s3 = u8"abc";
/* 16-bit wide string literal, of type char16_t[] */
char16_t* s4 = u"abc";
/* 32-bit wide string literal, of type char32_t[] */
char32_t* s5 = U"abc";
Tipos de enteros de ancho fijo (desde C99)
El encabezado <stdint.h>
proporciona varias definiciones de tipo entero de ancho fijo. Estos tipos son opcionales y solo se proporcionan si la plataforma tiene un tipo de entero del ancho correspondiente, y si el tipo con signo correspondiente tiene una representación complementaria de dos valores negativos.
Consulte la sección de comentarios para obtener sugerencias de uso de tipos de ancho fijo.
/* commonly used types include */
uint32_t u32 = 32; /* exactly 32-bits wide */
uint8_t u8 = 255; /* exactly 8-bits wide */
int64_t i64 = -65 /* exactly 64 bit in two's complement representation */
Constantes de punto flotante
El lenguaje C tiene tres tipos obligatorios de punto flotante real, float
, double
y long double
.
float f = 0.314f; /* suffix f or F denotes type float */
double d = 0.314; /* no suffix denotes double */
long double ld = 0.314l; /* suffix l or L denotes long double */
/* the different parts of a floating point definition are optional */
double x = 1.; /* valid, fractional part is optional */
double y = .1; /* valid, whole-number part is optional */
/* they can also defined in scientific notation */
double sd = 1.2e3; /* decimal fraction 1.2 is scaled by 10^3, that is 1200.0 */
El encabezado <float.h>
define varios límites para las operaciones de punto flotante.
Aritmética de punto flotante es la implementación definida. Sin embargo, la mayoría de las plataformas modernas (brazo, x86, x86_64, MIPS) usan operaciones de punto flotante IEEE 754 .
C también tiene tres tipos de puntos flotantes complejos opcionales que se derivan de lo anterior.
Interpretando declaraciones
Una peculiaridad sintáctica distintiva de C es que las declaraciones reflejan el uso del objeto declarado como sería en una expresión normal.
El siguiente conjunto de operadores con precedencia y asociatividad idénticos se reutilizan en los declaradores, a saber:
- el operador de "desreferencia" unaria
*
que denota un puntero; - el operador binario
[]
"suscripción de matriz" que denota una matriz; - el operador (1 + n) -ary
()
"llamada de función" que denota una función; - los
()
paréntesis de agrupación que anulan la precedencia y la asociatividad del resto de los operadores listados.
Los tres operadores anteriores tienen la siguiente prioridad y asociatividad:
Operador | Precedencia relativa | Asociatividad |
---|---|---|
[] (suscripción de matriz) | 1 | De izquierda a derecha |
() (llamada de función) | 1 | De izquierda a derecha |
* (desreferencia) | 2 | De derecha a izquierda |
Al interpretar declaraciones, uno tiene que comenzar desde el identificador hacia afuera y aplicar los operadores adyacentes en el orden correcto según la tabla anterior. Cada solicitud de un operador puede ser sustituida por las siguientes palabras en inglés:
Expresión | Interpretación |
---|---|
thing[X] | una matriz de tamaño X de ... |
thing(t1, t2, t3) | una función que toma t1 , t2 , t3 y regresa ... |
*thing | un puntero a ... |
De ello se deduce que el comienzo de la interpretación en inglés siempre comenzará con el identificador y terminará con el tipo que se encuentra en el lado izquierdo de la declaración.
Ejemplos
char *names[20];
[]
tiene prioridad sobre *
, por lo que la interpretación es: names
es una matriz del tamaño 20 de un puntero a char
.
char (*place)[10];
En caso de usar paréntesis para anular la precedencia, el *
se aplica primero: place
es un puntero a una matriz de tamaño 10 de char
.
int fn(long, short);
No hay ninguna prioridad de qué preocuparse aquí: fn
es una función que tarda long
, short
y devuelve int
.
int *fn(void);
Primero se aplica ()
: fn
es una función que void
y devuelve un puntero a int
.
int (*fp)(void);
Anular la prioridad de ()
: fp
es un puntero a una función que void
y devuelve int
.
int arr[5][8];
Las matrices multidimensionales no son una excepción a la regla; los operadores []
se aplican en orden de izquierda a derecha según la asociatividad en la tabla: arr
es una matriz de tamaño 5 de una matriz de tamaño 8 de int
.
int **ptr;
Los dos operadores de referencia tienen la misma prioridad, por lo que la asociatividad surte efecto. Los operadores se aplican en el orden de derecha a izquierda: ptr
es un puntero a un puntero a un int
.
Declaraciones multiples
La coma se puede usar como separador (* no * actuando como el operador de coma) para delimitar múltiples declaraciones dentro de una sola declaración. La siguiente declaración contiene cinco declaraciones:int fn(void), *ptr, (*fp)(int), arr[10][20], num;
Los objetos declarados en el ejemplo anterior son:
-
fn
: una función quevoid
y devuelveint
; -
ptr
: un puntero a unint
; -
fp
: un puntero a una función que tomaint
y devuelveint
; -
arr
: una matriz de tamaño 10 de una matriz de tamaño 20 deint
; -
num
:int
.
Interpretación alternativa
Debido a que las declaraciones reflejan el uso, una declaración también puede interpretarse en términos de los operadores que podrían aplicarse sobre el objeto y el tipo resultante final de esa expresión. El tipo que se encuentra en el lado izquierdo es el resultado final que se obtiene después de aplicar todos los operadores.
/*
* Subscripting "arr" and dereferencing it yields a "char" result.
* Particularly: *arr[5] is of type "char".
*/
char *arr[20];
/*
* Calling "fn" yields an "int" result.
* Particularly: fn('b') is of type "int".
*/
int fn(char);
/*
* Dereferencing "fp" and then calling it yields an "int" result.
* Particularly: (*fp)() is of type "int".
*/
int (*fp)(void);
/*
* Subscripting "strings" twice and dereferencing it yields a "char" result.
* Particularly: *strings[5][15] is of type "char"
*/
char *strings[10][20];