Lenguaje CPara Administradores de
Red
Fernando I. Díaz Sánchez
Lenguaje C
El Administrador de Red debe ser una de esas personas que, durante el trabajo, mientras menos lo vean las cosas estarán mejor. Nada mas imagínese a uno de ellos corriendo como pollo sin cabeza por toda la oficina o aun peor, que de pronto lo llame a Ud. y le diga que apague su PC porque va a restaurar en el servidor todos sus emails que han sido borrados.
Ser Administrador de Red no es fácil, y menos si todos piensan que no hacen nada. La verdad es que si uno de ellos está tranquilo y concentrado es porque algo bueno viene creando en su mente, está optimizando, aprendiendo, ordenando, ellos no están contentos si algo se puede hacer mejor y mas rápido.
Al aprender el lenguaje C las cosas para un Administrador de Red pueden salir mucho mejor y más rápido, deja de estar atado a programas que usa para crear los que realmente quiere y necesita. Conociendo el Lenguaje C las posibilidades de hacer cosas asombrosas son muchas. Es cierto, también pueden salir mal, sobre todo si no prestan atención a los detalles.
Este contenido es un pequeño intento por mejorar el aprendizaje de un Lenguaje que ha hecho posible que tengamos un digno trabajo.
>>Fids
Lenguaje C
MAXIMA: «Domina las variables, y dominaras el sistema…»
Lenguaje C
Variables en CSCRIPT I
Lenguaje C
Script I – Variables en C
>> Variables>> Direcciones de Memoria>> Tamaño>> Unidad Básica de Almacenamiento>> Tipos de Datos Básicos en C>> Tamaño de los tipos de datos básicos en C>> Limites de los tipos de datos básicos en C>> Cualificadores de los tipos de datos básicos en C>> Cualificadores de Tamaño>> Cualificadores de Valor>> Resumen de Tipos de Datos>> Tipos de Datos Especiales>> Prueba de Concepto - Detrás de las Variables>> Bonus Track - División de bytes & Protocolo IP>> Bonus Track – Endianness & Lilliput>> Tarea para la Casa>> Anexos>> Bibliografía
Lenguaje C
int edad = 10;
Lenguaje C
10 edad
int
0xf0113b1
VARIABLES
Las variables almacenan datos, eso no tiene ninguna novedad.
El problema es que en C, debemos conocer QUE ES REALMENTE una variable y DE QUE ESTA COMPUESTA
Aquí podemos ver una representación de la línea: int edad = 10;
Pero hay algo que no pusimos en el código…
Y QUE EXISTE REALMENTE
Lenguaje C
DIRECCIONES DE MEMORIA
Las variables almacenan datos, PERO nadie se pregunto en donde se guardan esos datos…
Por esa razón, tus programas no funcionan
Las variables se guardan en la MEMORIA del computador, y la única manera de encontrarlas entre tanta memoria es mediante su DIRECCION
El 2do problema en el lenguaje C es que las direcciones de memoria están identificadas con números HEXADECIMALES…
Y eso no es todo, le antepone las letras 0x
10 edad
int
0xf0113b1
Lenguaje C
TAMAÑO
Las variables almacenan datos en memoria, PERO nadie se pregunto hasta ahora que tamaño ocupan en memoria
Por esa razón, tus programas son lentos
El tamaño depende de que cosa quiero guardar en memoria. ¿Un Número?, ¿Una Letra?, ¿Una Fecha?, ¿Una Imagen?, etc.
Cuando hacemos programas, en realidad no decimos «que cosa quiero guardar», sino que «tipo de dato» voy a guardar
Y los tipos de datos tienen ya un tamaño predefinido en bits
10 edad
int
0xf0113b1
32 bits
Lenguaje C
TAMAÑO
Las variables almacenan datos en memoria que ocupan espacio según su tipo de dato y son identificadas a través de su dirección de memoria. PERO se olvidaron de preguntar cual el tamaño mínimo que podemos guardar
Por esa razón, tus programas son pesados
En las computadoras, el tamaño mínimo que puede ser identificado (mediante su dirección de memoria) es de 8 bits
Y 8 bits forman 1 byte…
10 edad
int
0xf0113b1
32 bits
Lenguaje C
UNIDAD BASICA DE ALMACENAMIENTO
0x0361a71
1 byte ¿Y que puedo guardar en 1 miserable byte?
8 bits, y cada bit solo puede representar 2 posibles valores (cero o uno, encendido o apagado, blanco o negro, sonido o silencio, etc., etc., etc.)
El mas conocido mundialmente es el de ceros y unos…
Así nació el uso mundial del Sistema Binario
8 bits
0
0
0
0
0
0
0
0
1 1 1 1 1 1 1 1
Lenguaje C
UNIDAD BASICA DE ALMACENAMIENTO
0x0361a71
1 byte ¿Por qué 8 y no 4, 5 ó 6?
Eso lo decidieron nuestros padres, que le vamos a hacer…
Ellos pensaron que la combinación de 8 bits da como resultado un buen balance para interpretar información y ahorrar complejidad en el seguimiento de las direcciones de memoria.
Después de todo, 255 valores diferentes no esta nada mal para representar algo
8 bits
0
0
0
0
0
0
0
0
1 1 1 1 1 1 1 1
Lenguaje C
UNIDAD BASICA DE ALMACENAMIENTO
0x0361a71
1 byte ¿255 valores? Y eso de donde salió
No has prestado atención…
Cada bit solo puede tomar uno de 2 posibles valores. El valor CERO o UNO. Por lo tanto, si juntamos 8 combinaciones de ceros y unos, tenemos:
0000 0000 = 00000 0001 = 10000 0010 = 20000 0011 = 3….1111 1111 = 255
8 bits
0
0
0
0
0
0
0
0
1 1 1 1 1 1 1 1
Lenguaje C
UNIDAD BASICA DE ALMACENAMIENTO
0x0361a71
1 byte ¿Y como se guardan las letras del teclado?
Las letras o caracteres, son en realidad números que el sistema operativo interpreta.
Por ejemplo, la letra ‘A’ en realidad corresponde con el número 65. La tecla ENTER corresponde con el número 13, etc.
Esa correspondencia (número -> carácter) obedece a estándares internacionales diseñados hace muchos años.
Un estándar conocido es el formato ASCII
8 bits
0
0
0
0
0
0
0
0
1 1 1 1 1 1 1 1
Lenguaje C
UNIDAD BASICA DE ALMACENAMIENTO
0x0361a71
1 byte Si 8 bits me permiten combinar 255 valores diferentes, y pueden servir para representar caracteres…
¿Cómo sabemos que el valor 65 hace referencia al número 65 y no a la letra ‘A’?
…Eso lo sabemos según el TIPO DE DATO que hemos utilizado
El 3er problema en C es la confusión entre los tipos de datos y el desconocimiento de como se almacenan en memoria
8 bits
0
0
0
0
0
0
0
0
1 1 1 1 1 1 1 1
Lenguaje C
TIPOS DE DATOS BASICOS EN C
¿Y no que todo era binario…?
Sí, todo lo que guardamos es binario, pero el Lenguaje C nos permite «CLASIFICAR» lo que guardamos en binario…
Los tipos de dato nos permiten darle un «sentido» a la información que guardamos
Técnicamente los tipos de dato se reducen a números de diferentes tamaños y formas
Es decir, el lenguaje C bailará con números…
char
int
floatdouble
Lenguaje C
TIPOS DE DATOS BASICOS EN C
Caracteres (visibles e invisibles)
Números Enteros
Números de doble precisión
char
int
floatdouble
Números de simple precisión
Lenguaje C
TAMAÑO DE LOS TIPOS DE DATOS BASICOS EN C
char
int
float
double
8 bits
32 bits
32 bits
64 bits
Lenguaje C
LIMITES DE TIPOS DE DATOS BASICOS EN C
0 a 255
-2147483648 a 2147483647
Números de doble precisión
char
int
floatdouble
Números de simple precisión
Lenguaje C
CUALIFICADORES DE TIPOS DE DATOS BASICOS EN C
shortlonglong longsignedunsigned
¿Cuali… qué?
Ahora sabemos bien el tamaño que ocupan los tipos de datos, pero uno llega a preguntarse:
¿Y si quiero guardar el valor 256, porque desperdiciar 16 bits que no usare con el int?
¿Y que pasa con los valores negativos?
¿Hay alguna manera de ajustar los tamaños de los tipos de datos para hacerlos mas flexibles?
Lenguaje C
CUALIFICADORES DE TIPOS DE DATOS BASICOS EN C
¿Qué son los cualificadores?
Son mecanismos en C que permiten «ajustar» los tamaños o límites de los tipos de datos básicos, ya sea a modo de expansión o de reducción en los bits que ocupan o en su representación numérica
De todos ellos, el cualificador signed es el cualificador por defecto.
Es decir, todas las variables que se declaren en un programa en C tendrán el cualificador signed a menos que se indique lo contrario
shortlonglong longsignedunsigned
Lenguaje C
CUALIFICADORES DE TAMAÑO
int32 bits
short int16 bits
long int64 bits
Lenguaje C
char8 bits
CUALIFICADORES DE TAMAÑO
¿Y nuestro querido char
porque no tiene
cualificadores de tamaño?
Lenguaje C
CUALIFICADORES DE VALOR
unsigned char
unsigned int
unsigned short
unsigned long
8 bits
32 bits
16 bits
64 bits
Lenguaje C
RESUMEN DE TIPOS DE DATOSTipo de dato signed /
unsignedLimite signed Limite unsigned
char 8 bits -128 a 127 0 a 255
short [int] 16 bits -32768 a 32767 0 a 65535
int 32 bits -2147483648 a 2147483647 0 a 4294967295
long [int] 64 bits -9223372036854775808 to 9223372036854775807
0 to 18446744073709551615
long long [int] 64 bits -9223372036854775808 to 9223372036854775807
0 a 9223372036854775807
float 32 bits 1.17549e-38 to 3.40282e+38 No existe
double 64 bits 2.22507e-308 to 1.79769e+308 No existe
long double 128 bits 2.22507e-308 to 1.79769e+308 No existe
Nota: Los tipos de datos float, double y long double no usan cualificadores de valor (signed o unsigned)
Lenguaje C
RESUMEN DE TIPOS DE DATOS
Nota: Los tipos de datos mostrados son de un servidor Red Hat 6.2 64 bits , es posible que los valores difieran en otros SO
Lenguaje C
TIPOS DE DATOS ESPECIALES
¿Qué tienen de especial?
El tipo dato bool solo permite registrar los valores enteros CERO y UNO
Internamente, el tipo de datos bool ocupa 1 byte (al igual que char), pero no se permite guardar números diferentes de cero o uno.Si el valor asignado es diferente de CERO, la variable de tipo bool tomara el valor UNO.
Este comportamiento nos permite representar los valores VERDADERO (true,1) o FALSO (false,0). Para poder usar bool debemos incluir la librería stdbool.h
boolvoid
Lenguaje C
TIPOS DE DATOS ESPECIALES
Nótese que usamos el header stdbool.h para poder usar el tipo de dato bool
bool
Nota: Una confusión común es no tener claro si 1 es FALSO o VERDADERO. Una forma sencilla de recordarlo es preguntarse cuanto vale un billete FALSO
Lenguaje C
TIPOS DE DATOS ESPECIALES
¿Qué tienen de especial?
El tipo dato void permite guardar cualquier información para luego ser recuperada según el tipo de dato que nos interese
El tipo de datos void ocupa 8 bytes debido a que lo que guarda en realidad son direcciones de memoria
Para poder usar una variable del tipo void, deben usarse en forma de punteros (void *), de lo contrario ocurrirá un error de compilación
boolvoid
Lenguaje C
int edad = 10;
Lenguaje C
DETRAS DE LAS VARIABLES
edad
int
0x7ffffc127f27
32 bits
8 bits 8 bits 8 bits 8 bits
0000 10100000 00000000 00000000 0000
100x7ffffc127f26 0x7ffffc127f25 0x7ffffc127f24
Lenguaje C
DETRAS DE LAS VARIABLES
Se puede apreciar que la variable edad abarca 4 bytes de memoria porque es de tipo int.
En cambio los valores de tipo char solo abarcan 1 byte
Ir a siguiente dirección de memoria
Ir a siguiente dirección de memoria
Ir a siguiente dirección de memoria
???
Lenguaje C
DETRAS DE LAS VARIABLES – PRUEBA DE CONCEPTO
DEMOSTRADO !
El lenguaje C solamente maneja bits con sus posiciones de memoria; Es el programador quien decide como quiere interpretar los bits valiéndose de los tipos de datos proporcionados por el lenguaje
Nota: EL orden de los caracteres se debe a que se la arquitectura trabaja con LittleEndian del cual trataremos ma adelante
Lenguaje C
DETRAS DE LAS VARIABLES – PRUEBA DE CONCEPTO
DEMOSTRADO !
El tipo de dato void permite ubicarse en cualquier posición de memoria de cualquier variable del programa
¿Cuándo USAR VOID?
El uso del tipo de dato void suele utilizarse en programas complejos que requieren alta velocidad y flexibilidad en la manipulación de datos. Su desventaja es lo peligroso que puede llegar a ser y lo engorroso en su sintaxis
Lenguaje C
DETRAS DE LAS VARIABLES
Las variables son estructuras del lenguaje C que permiten almacenar información que es accedida mediante una dirección de memoria y que ocupan un tamaño según sea el tipo de dato y cualificador con las que fueron declaradas.
El sistema operativo es el responsable de separar el espacio necesario por cada variable a utilizar
El programador es el responsable de darle la adecuada interpretación a los datos así como su adecuada manipulación.
Las variables guardan información binaria agrupada en bloques de 8 bits Dependiendo de la arquitectura del equipo donde se ejecuta un programa
en C, las variables pueden ser almacenadas ya sea en formato Big Endian o Little Endian
Conociendo el funcionamiento de las variables podremos optimizar nuestros programas y hackear el sistema!
Lenguaje C
BONUS TRACK
0x0361a71
1 byte
8 bits
0
0
0
0
0
0
0
0
1 1 1 1 1 1 1 1
4 bits4 bits
Dividiendo los bytes
Si bien la unidad básica de almacenamiento es 1 byte, sus 8 bits que lo componen pueden ser referenciados mediante variables
Por ejemplo, podemos crear 2 variables cada una de 4 bits o inclusive podemos crear 8 variables de 1 bit cada una
Esto es particularmente útil cuando diseñamos protocolos de comunicación para redes de computadoras
Lenguaje C
BONUS TRACK
0x0361a71
1 byte
8 bits
0
0
0
0
0
0
0
0
1 1 1 1 1 1 1 1
5 bits3 bits
Dividiendo los bytes
Es importante recordar que si bien podemos fragmentar los bytes, no podemos reducir su tamaño de almacenamiento.
Imaginemos que necesitamos guardar los días de la semana (que son 7) e ingenuamente pensamos que podremos optimizar espacio en disco si declaramos una variable de 3 bits de longitud
La sorpresa será que la variable de 3 bits declarada sigue teniendo un tamaño de 1 byte
Lenguaje C
BONUS TRACK
0x0361a71
1 byte
8 bits
0
0
0
0
0
0
0
0
1 1 1 1 1 1 1 1
5 bits3 bits
Dividiendo los bytes
¿Entonces de que me sirve?
Nos sirve de mucho si queremos ahorrar espacio al máximo, siempre y cuando tengamos mas de 1 variable que podamos incluir en 1 byte
Ejemplo:Necesitamos 2 variables para almacenar el día de la semana y el día del mes
Lenguaje C
BONUS TRACK
0x0361a71
1 byte
8 bits
0
0
0
0
0
0
0
0
1 1 1 1 1 1 1 1
5 bits3 bits
Dividiendo los bytes
¿Entonces de que me sirve?
El programador común hará algo similar a esto:
int dia_semana = 7;int dia_mes = 31;
Estas variables consumen 64 bits (cada int ocupa 32 bits)
Lenguaje C
BONUS TRACK
0x0361a71
1 byte
8 bits
0
0
0
0
0
0
0
0
1 1 1 1 1 1 1 1
5 bits3 bits
Dividiendo los bytes
¿Entonces de que me sirve?
El programador obsesionado con el tamaño de sus variables hará esto:
struct fecha{unsigned char dia_semana:3;unsigned char dia_mes:5;
};
Estas variables juntas consumen solo 8 bits
Lenguaje C
BONUS TRACK
0x0361a71
1 byte
8 bits
0
0
0
0
0
0
0
0
1 1 1 1 1 1 1 1
5 bits3 bits
Dividiendo los bytes
Wow !
64 bits vs 8 bits es una diferencia bastante grande cuando se trata de redes y comunicaciones.
Es por eso que los protocolos aprovechan esta característica del lenguaje C para hacer de las suyas y llevar al limite el envío de información en pocos bits
Lenguaje C
BONUS TRACKPrueba de Concepto
Demostrado !
Se puede reducir significativamente el tamaño de las variables agrupándolas en estructuras y dividiendo sus bytes.
Lenguaje C
BONUS TRACK – PROTOCOLO IPPrueba de Concepto
Demostrado !
Se puede apreciar una implementación (barata por supuesto) del protocolo IP el cual aplica el concepto de división de bytes
Un paquete IP normal ocupa 20 bytes gracias a este mecanismo.
De esta manera se ahorra espacio al enviar trafico por la red
Lenguaje C
BONUS TRACK - ENDIANNESS
edad
int
0x7ffffc127f27
8 bits 8 bits 8 bits 8 bits
0000 10100000 00000000 00000000 0000
100x7ffffc127f26 0x7ffffc127f25 0x7ffffc127f24
¿En que orden se almacenan los bits?
Uno de los aspectos mas confusos cuando se aprende el lenguaje C a fondo es la forma en la que se almacenan físicamente los datos.
Lenguaje C
BONUS TRACK - ENDIANNESS
Despedazando el Byte
La forma en la que se numera un byte es de derecha a izquierda. Esto a veces no es simple de entenderlo. Pondremos un ejemplo sencillo
Imaginemos que pudiéramos guardar números decimales dentro de un byte. ¿Cuál sería la manera correcta de numerar el 765?
¿00000765 o 76500000 ?
A algunos le resulta razonable la 2da forma hasta que se encuentran con el problema de numerar 7650 o 76500
0x0361a71
7
6
5
4
3
2
1
0
10
MSB LSB
0
0
0
0
1
0
1
0
Lenguaje C
BONUS TRACK - ENDIANNESS
Despedazando el Byte
Eso no es todo. Cada byte contiene 2 partes bien diferenciadas a tener en cuenta.
La posición 0 (cero) que se encuentra mas a la derecha se le conoce como LSB (Less Significant Bit) o Bit menos significativo
La posición 7 que se encuentra mas a la izquierda, se le conoce como MSB (Most Significant Bit) o Bit Mas significativo
Son utilizados para realizar operaciones con bits 0x0361a71
7
6
5
4
3
2
1
0
10
MSB LSB
0
0
0
0
1
0
1
0
Lenguaje C
BONUS TRACK - ENDIANNESSPrueba de Concepto
Demostrado !
Los datos son almacenados en bits agrupados en 8 formando 1 byte. Se almacenan siguiendo la numeración tradicional (de derecha a izquierda)
Lenguaje C
BONUS TRACK - ENDIANNESS¿Y cuál es el problema?
No hay ningún problema para almacenar 1 byte. El problema viene cuando queremos almacenar información multibyte (tipos de dato diferentes de char)
32 bits ( 4 bytes)
byte 1byte 2byte 3byte 4
0 0 0 10
32 bits ( 4 bytes)
byte 1byte 2byte 3byte 4
10 0 0 0
Little Endian
Big Endian
¿Por qué es un problema?
Porque todos los equipos con un formato Little Endian leerán de forma incorrecta la información proveniente de los equipos con formato Big Endian y viceversa
En nuestro ejemplo, el byte 1 es distinto en ambos formatos. Babilonia otra vez!
Lenguaje C
BONUS TRACK - ENDIANNESS¿De donde provienen los nombres Little Endian y Big Endian?
Los nombres fueron extraídos de la novela «Los viajes de Gulliver» que relata la disputa en Lilliput por la forma de comer los huevos cocidos. Unos exigían que debía ser por la parte pequeña (Little Endian) y otros por la parte grande (Big Endian)
32 bits ( 4 bytes)
byte 1byte 2byte 3byte 4
0 0 0 10
32 bits ( 4 bytes)
byte 1byte 2byte 3byte 4
10 0 0 0
Little Endian
Big Endian
El formato Little Endian es el mas común, sin embargo algunas arquitecturas trabajan con Big Endian.
Big Endian también es muy utilizado en la transmisión de datos de red, por lo tanto la mayoría de protocolos lo implementa con este formato
Lenguaje C
BONUS TRACK - ENDIANNESS
Prueba de Concepto
Demostrado !
El formato Little Endian empieza su numeración desde el extremo izquierdo
Lenguaje C
TAREA PARA LA CASA
¿No hay cuando acabar con estos tipos?
El lenguaje C no solo tiene tipos de datos básicos, también tiene otros tipos de datos que permiten manipular información mas compleja (como el tiempo)
Incluso, el lenguaje C permite ‘crear’ nuestros propios tipos de datos mediante estructuras y uniones para representar entidades mas complejas que un tipo de dato básico no basta para completarlo
Investiga que otros tipos de datos no básicos podemos usar en C
clock_ttime_twchar_twint_t
Lenguaje C
TAREA PARA LA CASA
¿No hay cuando acabar con estos tipos?
El lenguaje C es muy popular en el mundo y ha tenido varios estándares mundiales que rigen su buen uso y mejoras en el tiempo.
Entre los estándares mas conocidos tenemos al estándar C99 (1999) y C11 (2011) cuyas reglas han sido agregadas en los diferentes compiladores de C.
En estos estándares se recomienda usar tipos de datos enteros basados en su tamaño. Investiga cuales son y para que sirven
int8_tuint32_tintptr_tintmax_tsize_t… etc
Lenguaje C
Anexos¿Qué necesito para programar en C bajo Linux?
gcc, gdb, vim
¿Cómo compilar un programa C en Linux?
gcc mi-programa.c -g -o mi-programa.exe
¿Cómo depurar un programa C en Linux?
gdb mi-programa.exe
¿Qué necesito para programar en C bajo Windows?
Visual C++ ó Borland C ó C Builder, etc
Nota: La extensión .exe es solo para referencia sencilla de que se trata de un ejecutable, no es necesario por lo tanto agregarle dicha extensión en realidad
Nota: Si se desea programar con el estándar C11 se deberá obtener una copia del compilador gcc 4.8.1.
Lenguaje C
BibliografiaThe C Programming Language, 2nd Edition, B. Kernighan, Dennis Ritchie.
The Art and Science of C, Eric S. Roberts.
Programming in C, 3rd Edition, Stephen G. Kochan
Programación en C, Metodología, algoritmos y estructura de datos. Luis Joyanes Aguilar
C Programming A Modern Approach. Second Edition. K.K.King
Essential C. Standford CS Education Library. Nick Parlante
Lenguaje C
BibliografiaBit Numbering (http://en.wikipedia.org/wiki/Bit_numbering)
Endianness (http://en.wikipedia.org/wiki/Endianness)
White Paper: Endianness or Where is Byte 0?. Bertrand Blanc, Bob Maaraoui
Understanding Big and Little Endian Byte Order | Better Explained (http://betterexplained.com/articles/understanding-big-and-little-endian-byte-order)
Writing endian-independent code in C. Harsha S. Adiga (http://www.ibm.com/developerworks/aix/library/au-endianc/index.html?ca=drs-)
ISO/IEC 9899:TC2 (C99)