Professional Documents
Culture Documents
Introducción
Las expresiones dan “vida” a los programas de computadora. Esas expresiones, por
supuesto, se construyen a través de un lenguaje de programación, en este caso el C, y
están constituidas por las operaciones que aplican a los datos para obtener la
información buscada. Por eso, en esta unidad nos estaremos enterando de los tipos de
datos y los operadores, que permiten crear expresiones en el lenguaje C.
3.1 Variables
Los ejemplos:
int edad_p1=4; // Empieza con letra, usa letras, dígitos y guión bajo.
int B=8; // Es diferente a b
int b=9; // Es diferente a B
// int return; // <-- No se puede usar una palabra reservada como nombre de variable
float promedio;// Nombre de variable auto-descriptivo
Tipo Descripción
char Carácter, de tamaño 1
int Entero
float Punto flotante de simple precisión
double Punto flotante de doble precisión
El tipo de dato int, puede recibir los modificadores short y long, que corresponden a
entero corto y entero largo, respectivamente, mientras al double se puede aplicar
long. La presencia o no del signo se indica con las palabras signed y unsigned. Si
no se usa, se asume signed.
Una mención especial merece el tipo char, que realmente es de tipo entero, pero que
puede almacenar cualquier tipo de carácter. Veamos la ductilidad de este tipo de dato,
con el siguiente ejemplo:
A propósito, la tabla ASCII estándar, en la que se basan los códigos numéricos dados a
los caracteres se presenta en el documento, “Aprenda lenguaje ANSI C como si
estuviera en primero”, de la Escuela Superior de Ingenieros Industriales- Universidad
de Navarra, España, con la siguiente imagen:
En el printf() usamos dos formatos para 'A'. El primero es “%c”, para imprimir la letra
tal cual, y el segundo “%d”, con lo que obtenemos el valor numérico de la letra, en
Los tamaños en bytes de los tipos de datos básicos se pueden obtener en C, mediante
el operador sizeof(). El siguiente código fuente calcula y muestra los tamaños:
int main()
{
system("clear");
printf("Tamaño de datos básicos\n");
printf("=======================\n");
printf("Tipo\tTamaño en bytes\n");
printf("====\t===============\n");
printf("char\t%ld\n",sizeof(char));
printf("int\t%ld\n",sizeof(int));
printf("float\t%ld\n",sizeof(float));
printf("double\t%ld\n",sizeof(double));
return 0;
}
El resultado de la ejecución:
Los valores mínimo y máximo posibles, dependen del procesador que se esté usando.
Es una de las críticas que se le hace al lenguaje C, en el sentido que el hecho
mencionado crea problemas de portabilidad(llevar de una plataforma a otra) de las
aplicaciones. Los archivos de cabecera <limits.h> y <float.h> del sistema en el cual
se trabaja, proporcionan los valores mencionados, según se ve en las siguientes líneas
de código:
#include <stdio.h>
#include <limits.h>
#include <float.h>
int main()
{
printf("*\n");
printf("Caracter con signo\n");
printf("Mínimo: %d\n",CHAR_MIN);
printf("Máximo: %d\n",CHAR_MAX);
printf("*\n");
printf("Caracter sin signo\n");
printf("Mínimo: 0\n");
printf("Máximo: %u\n",UCHAR_MAX);
printf("*\n");
…
...
Se muestra parte del resultado de la ejecución, en una notebook HP, con procesador
AMD de 64 bits:
*
Caracter con signo
Mínimo: -128
Máximo: 127
*
Caracter sin signo
Mínimo: 0
Máximo: 255
*
*
Entero corto con signo
Mínimo: -32768
Máximo: 32767
*
Entero corto sin signo
Mínimo: 0
Máximo: 65535
*
…
…
Los ejemplos:
Como se ve en la primera parte se crean los nuevos tipos de datos y más abajo se
definen variables con los tipos de datos creados. El programa fuente completo se ve
así:
nro_corto=24;
nro_real=8.2;
letra='G';
printf("Corto: %d Real: %2.1f Letra: %c\n",nro_corto,nro_real,letra);
return 0;
} // Fin de programa
El resultado de la ejecución:
Siguiendo en la línea de los tipos de datos creados por el programador veamos lo que
es una estructura. El concepto básico asociado a su creación y manipulación es el de
registro. Así, el nuevo tipo de dato definido agrupa uno o mas variables de distintos
tipos, conformando una unidad asociada a una persona, hecho o acontecimiento.
Podríamos, por ejemplo, necesitar guardar los datos de un libro en un archivo. Como
archivo es un conjunto de registros relacionados entre si, lo que hacemos es, definir el
formato de cada de los registros, como un nuevo tipo de dato. Posteriormente para
manipular cada registro dentro del programa definimos una estructura asociándola
con el nuevo tipo de dato, como se ve en el ejemplo:
Ingrese el codigo:1
Ingrese el título del libro:Rayuela
Ingrese el nombre del autor:Cortázar
Registro-->: 00001 Rayuela Cortázar
printf("Ingrese el codigo:");
scanf("%d",&libro.codigo);
printf("Ingrese el título del libro:");
scanf("%s",libro.titulo);
printf("Ingrese el nombre del autor:");
scanf("%s",libro.autor);
// Imprime el registro
printf("Registro-->: %05d %-20s %-20s\n",libro.codigo,libro.titulo,libro.autor);
return 0;
} // Fin de programa
La palabra clave union permite definir un tipo de dato muy similar definido por struct.
En este caso se trata de ahorrar espacio de almacenamiento, utilizando uno común
para guardar dos o más datos diferentes pero de raíz común. Por ejemplo, si sabemos
que el código que identifica a un país(“Paraguay”) es la primera letra de su
nombre('P') podemos almacenar ambos datos en un espacio común como se muestra
en el siguiente ejemplo:
En la primera parte de crea el nuevo tipo de dato upais, definiendo nombre con 30
caracteres. Esa será la máxima longitud usada, la definición de codigo, con tamaño 1
no ocupa la posición 31 pues hace referencia a la primera posición de nombre, es
decir que la primera posición de nombre es el mismo espacio al que se refiere codigo.
El segundo uso de unión se encarga de definir la estructura pais con el tipo de dato
definido upais. Donde se nota claramente el espacio común que ocupan ambos datos
es en la parte procedimental, pues el único item que se carga es el nombre. Veamos la
ejecución del programa de prueba:
3.3 Constantes
Una constante es aquel carácter o grupo de caracteres que se usa en forma literal en
la construcción de expresiones dentro de un programa, es decir no está contenida
dentro de una variable. Podemos agruparlas en constantes sin nombre y con nombre.
➢ Un dato tipo punto flotante asume doble precisión a menos que se use
modificador.
➢ Un carácter se delimita con apóstrofos.
➢ Una cadena se delimita con comillas.
#include <stdio.h>
#include <stdlib.h>
#define elementos 100
int codigo_libro[elementos];
char nombre_libro[elementos][30];
float precio_libro[elementos];
char autor_libro[elementos][30];
char editorial_libro[elementos][30];
int main()
{
printf("Hay %d libros\n",elementos);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
const short codigo_postal= 234;
int main()
{
system("clear");
// codigo_postal=432;
printf("Código postal: %d\n",codigo_postal);
return 0;
}
No se generó el ejecutable, pues hay error de compilación por el intento de modificar la constante.
Una modalidad bastante interesante de definir constantes con nombre es usando la llamada constante
de enumeración, de la cual se muestra un ejemplo:
enum {domingo=1,lunes, martes, miercoles, jueves, viernes, sabado} dia; // Define lista ennumerada
La línea precedente, la parte declarativa del programa, muestra la definición de 7 constantes con
nombre, cuyo valor inicial es el 1 asociado a la constante domingo y se agrupan bajo el nombre de dia. Si
no se define otro valor para lunes, tomará el valor 2 y así sucesivamente. Si domingo no se inicializa con
1, toma el valor 0, por lo que, según la progresión sábado tendría el valor 6.
Al ejecutar se muestra:
3.4 Declaraciones
En lenguaje C, es requisito declarar las variables a ser usadas. La forma general es:
Sin modificador:
int edad;
Esta última forma aunque ocupe más espacio ayuda a hacer un comentario por cada
variable facilitando la auto-documentación y legibilidad del programa fuente.
#include <stdio.h>
#include <stdlib.h>
short a,b,c;
float b1,c1;
int main()
{
system("clear");
a=4;
b=2;
printf("Suma\n");
c=a+b; // Suma o adición
printf("\t%d + %d = %d\n",a,b,c);
printf("Resta\n");
El resultado de la ejecución:
Suma
4+2=6
Resta
4-2=2
Multiplicación
4*2=8
División
4*2=2
4 / 3.00 = 1.33
Resto
El resto de 4/2 es 0
El resto de 4/3 es 1
Negación
A No A
V F
F V
Conjunción
A B AyB
V F F
F V F
F F F
V V V
Disyunción
A B AoB
V F V
F V V
V V V
F F F
Valor inicial de a = 10
Valor de a en el momento de hacer la operacion ++a = 11
Valor de a después de hacer ++a = 11
Valor inicial de a = 10
Valor de a en el momento de hacer la operación a++ = 10
Valor de a después de hacer a++ = 11
Valor inicial de a = 10
Valor de en el momento de hacer la operación --a = 9
Valor de a después de hacer --a = 9
Valor inicial de a = 10
Valor de a en el momento de hacer la operación a-- = 10
Valor de a después de hacer a-- = 9
a=10;
printf("Valor inicial de a = %hd\n",a);
b=--a;
printf("Valor de en el momento de hacer la operación --a = %hd\n",b);
printf("Valor de a después de hacer --a = %hd\n",a);
a=10;
printf("Valor inicial de a = %hd\n",a);
b=a--;
printf("Valor de a en el momento de hacer la operación a-- = %hd\n",b);
printf("Valor de a después de hacer a-- = %hd\n",a);
return 0;
} // Fin de programa
Cuando se trata de programación a bajo nivel, es decir, aquella que está más “cerca”
del hardware, es algo usual que se recurra a la manipulación de bits u operaciones bit
a bit (bitwise), como sería el caso de software para controlar microcontroladores, con
requerimientos de configurar los registros para usar el hardware, incluido el acceso a
puertos de comunicación, realizar operaciones más eficaces y eficientes, y validar los
datos de entrada/salida, entre otras prestaciones.
AND: En el caso de que ambos bits comparados tengan valor 1 el resultado es 1(uno).
En todas las otras combinaciones se genera 0(cero). El formato general es:
z=x&y
donde & es el operador, x e y son los dos números decimales comparados y el
resultado se carga en z, que es el nuevo número generado.
OR: Si ambos bits comparados tienen valor 0(cero) el resultado es 0(cero). En los
casos restantes el valor es 1(uno). La forma general de uso:
z=x|y
siendo | el operador, x e y son los números decimales comparados generando z.
XOR: También conocido como OR exclusivo. Si los bits comparados tienen igual valor,
el resultado es 0(cero). En situación contraria se genera 1(uno). El esquema de uso se
muestra a continuación:
z=x^y
donde ^ es el operador, x e y son los números decimales comparados almacenándose
el resultado en z.
Para ilustrar mejor, resumimos lo que se puede hacer con los operadores de este tipo
en la siguiente tabla:
Ejemplos
Operación Resultado
Operador Nombre Decimal Binario Decimal Binario
& AND 5&6 101 & 110 4 100
| OR 5|6 101 | 110 7 111
^ XOR 5^6 101 ^ 110 3 011
>> Desplazamiento a la derecha 5 >> 1 101 >> 1 2 0010
<< Desplazamiento a la izquierda 5 << 1 101 << 1 10 1010
~ Complemento a uno ~5 ~00000101 -6 11111010
3.10 Expresiones
a=4;
b=2;
printf("Suma\n");
c=a+b; // Suma o adición
printf("\t%d + %d = %d\n",a,b,c);
Suma
4+2=6
Resta
4-2=2
Multiplicación
4*2=8
División
4/2=2
4 / 3.00 = 1.33
Resto
El resto de 4/2 es 0
El resto de 4/3 es 1
Expresiones lógicas, que son consecuencia del uso operadores relacionales. Por
ejemplo, las expresiones a > b, a < b y a == b, son de tipo lógico, pues tienen dos
resultados posibles: que sea verdadero o falso. La comparación retorna 0 si la
expresión es falsa o un valor distinto de cero si es verdadera. Veamos ejemplos:
Valor de a:7
Valor de b:5
Para a = 7 y b = 5
7 > 5 devuelve 1
7 < 5 devuelve 0
7 == 5 devuelve 0
letra = 'A';
strcpy(saludo,”Buenos”);
saludo, haríamos:
strcat(saludo," dias");
Buenos dias
Mostramos el programa fuente completo que hace uso de las expresiones cadena:
Siendo t una variable tipo char, se cargará en ella 'p' si es par o 'i' en caso contrario.
En el printf() se vuelve a usar una expresión condicional, pero ya para imprimir “par” o
“impar” de acuerdo a que t sea 'p' o 'i'. Pero podemos simplificar las dos líneas de
código en una, escribiendo:
Como se ve, se pregunta directamente por el valor del resto de x/2 para construir la
expresión condicional y retornar el mensaje adecuado a la situación. Veamos algunos
ejemplos de ejecución:
El menor entre 9 y 7 es 7
9 es impar
10 es par
En este apartado vamos a ver como convertir datos de un tipo a otro. Existen dos
formas de convertir datos. Una de ellas es la implícita y la otra la explicita, también
llamada casting, en inglés. En el caso de las conversiones implícitas partamos de un
caso práctico. Quiero sumar los números 4 y 2.2. Como se ve 4 es entero y 2.2 real.
Teniendo las siguientes declaraciones:
El resultado:
4 + 2.2 = 6.2
¿Qué sucedió? Para realizar la conversión se realizó una verificación de cual de los
operandos tenía mayor jerarquía de tipo de datos. En este caso el float de y es de
mayor jerarquía que el int de x. Por lo tanto, el resultado en z es de tipo float. Es decir
se realizo la conversión implícita a float. La jerarquía usada en la conversión se da de
acuerdo de la siguiente lista, de mayor a menor:
long double, double, float, unsigned long, long, unsigned int, int, char
donde long double es el de mayor jerarquía y char el de menor.
y la asignación:
4 + 2.2 = 6
Como se ve hay una perdida de datos, por lo que hay extremar cuidados con este tipo
de conversión.
4 + 2.0 = 6
Las operaciones de una expresión se rigen por la jerarquía que tienen definida los
operadores. Por ejemplo, si tengo la expresión:
5+7*3
(5+7)*3
El resultado es:
36
5+(7*3)
26
printf("5+7*3 = %d\n",5+7*3);
5+7*3 = 26
Es evidente que ejecutó el producto en primer lugar. En este caso se puede afirmar
que el producto tiene mayor prioridad que la suma.
Tomemos la línea:
3*7/3%2 = 1
3.14 Bibliografía
Este trabajo se libera bajo el tipo de licencia PP, de la expresión guaraní "Pejapo
Pejaposeva" y en castellano sería, "Hagan Lo Que Quieran"(HLQQ). Con una licencia PP
ya saben que pueden copiar "in extenso", duplicar, reutilizar, adaptar, re-mezclar y redistribuir,
sin rubores ni remordimientos. Para mí, un docente que no comparte sus conocimientos, obras
u otros recursos y servicios, y piensa solo en lo que le "costó" adquirir y como "recuperar" eso,
no merece la distinción de llamarse tal. Con eso no digo que se muera de hambre y no cobre
por sus servicios. Pero si empieza a (pensar en) lucrar, ahí ya no nos entendemos.