En este capítulo se ofrece una breve historia del desarrollo del lenguaje C y se consideran también sus características.
En el resto del capítulo se ven los aspectos básicos de los programas de C, tales como su estructura, la declaración de variables, tipos de datos y operadores.
El proceso de desarrollo del lenguaje C se origina con la creación de un lenguaje llamado BCPL, que fue desarrollado por Martin Richards. El BCPL tuvo influencia en un lenguaje llamado B, el cual se usó en 1970 y fue inventado por Ken Thompson y que permitió el desarrollo de C en 1971, el cual lo inventó e implementó Dennis Ritchie. Para 1973 el sistema operativo UNIX estaba casi totalmente escrito en C.
Durante muchos años el estándar para C fue la versión 5 del sistema operativo UNIX, documentada en ``The C Programming Language'' escrito por Brian W. Kernighan and Dennis M. Ritchie in 1978 comúnmente referido como K&R.
Posteriormente se hicieron varias implementaciones las cuales mostraban las siguientes tendencias:
Esto originó que en el verano de 1983 se estableciera un comité para resolver estas discrepancias, el cual empezó a trabajar en un estándar ANSI C, la cual fue completada en 1988.
Algunas de las características más importantes que definen el lenguaje y que han permitido que sea tan popular, como lenguaje de programación son:
Las diversas razones por la cual se ha convertido en un lenguaje de uso profesional son:
Un punto en contra es que tiene una detección pobre de errores, lo cual en ocasiones es problemático para los principiantes.
Un programa de C tiene básicamente la siguiente forma:
Para un programa se debe tener una función main()
.
Una función tiene la forma:
tipo nombre_de_la_funcion (parámetros) { variables locales sentencias de C }
Si la definición del tipo es omitida, C asume que la función regresa un tipo entero. Nota: Lo anterior puede ser una fuente de problemas en un programa.
A continuación se muestra un primer programa:
/* Programa ejemplo */ main() { printf( "Me gusta C\n" ); exit (0); }
NOTAS:
printf
es una función estándar de C, la cual es llamada en la función main()
.
\n
significa salto de línea. Salida formateada.
exit()
es también una función estándar que hace que el
programa termine. En el sentido estricto no es necesario ya que es la
última línea de main()
y de cualquier forma terminará el programa.
En caso de que se hubiera llamado a la función printf
de la
siguiente forma:
printf(".\n.1\n..2\n...3\n");
La salida tendría la siguiente forma:
.1 ..2 ...3
C tiene los siguientes tipos de datos simples:
Los tipos de datos básicos tiene varios modificadores que
les preceden. Se usa un modificador para alterar el significado de un
tipo base para que encaje con las diversas necesidades o situaciones.
Los modificadores son: signed
, unsigned
, long
y short
.
En los sistemas UNIX todos los tipos int
son long int
, a menos que se especifique explícitamente short int
.
Nota: no hay un tipo booleano en C -- se deberá usar char
, int
o
aún mejor unsigned char
.
signed
, unsigned
, long
y short
pueden ser usados con los tipos char
e int
. Aunque es permitido el uso de signed
en enteros, es redundante porque la declaración de entero por defecto asume un número con signo.
Para declarar una variable en C, se debe seguir el siguiente formato:
tipo lista_variables;
tipo es un tipo válido de C y lista_variables puede consistir en uno o más indentificadores separados por una coma. Un identificador debe comenzar con una letra o un guión bajo.
Ejemplo:
int i, j, k; float x,y,z; char ch;
Una varible global se declara fuera de todas las funciones, incluyendo a la función main()
. Una variable global puede ser utilizada en cualquier parte del programa.
Por ejemplo:
short numero, suma; int numerogr, sumagr; char letra; main() { ... }
Es también posible preinicializar variables globales usando el operador de asignación =
, por ejemplo:
float suma= 0.0; int sumagr= 0; char letra= 'A'; main() { ... }
Que es lo mismo que:
float suma; int sumagr; char letra; main() { suma = 0.0; sumagr= 0; letra = 'A'; ... }
Dentro de C también se permite la asignación múltiple usando el operador
=
, por ejemplo:
a = b = c = d = 3;
...que es lo mismo, pero más eficiente que:
a = 3; b = 3; c = 3; d = 3;
La asignación múltiple se puede llevar a cabo, si todos los tipos de las variables son iguales.
Se pueden redefinir los tipos de C usando typedef
.
Como un ejemplo de un simple uso se considera como se crean dos nuevos
tipos real y letra. Estos nuevos tipos pueden ser usados de igual forma
como los tipos predefinidos de C.
typedef float real; typedef char letra; /* Declaracion de variables usando el nuevo tipo */ real suma=0.0; letra sig_letra;
El lenguaje C usa salida formateada. La función printf
tiene un
caracter especial para formatear (%) -- un caracter enseguida define un
cierto tipo de formato para una variable.
%c caracteres
%s cadena de aracteres
%d enteros
%f flotantes
Por ejemplo:
printf("%c %d %f",ch,i,x);
La sentencia de formato se encierra entre " "
, y enseguida las
variables. Asegurarse que el orden de formateo y los tipos de datos de las variables coincidan.
scanf()
es la función para entrar valores a variables. Su formato es
similar a printf
. Por ejemplo:
scanf("%c %d %f %s",&ch, &i, &x, cad);
Observar que se antepone &
a los nombres de las varibles, excepto a la cadena de caracteres. En el capítulo 8 que trata sobre apuntadores se revisará más a fondo el uso de este operador.
ANSI C permite declarar constantes. Cuando se declara una constante es un poco parecido a declarar una variable, excepto que el valor no puede ser cambiado.
La palabra clave const
se usa para declarar una constante, como se muestra a continuación:
const a = 1; int a = 2;
Notas:
const
antes o después del tipo.
La directiva del preprocesador #define
es un método más flexible para definir constantes en un programa.
Frecuentemente se ve la declaración const
en los
parámetros de la función. Lo anterior simplemente indica que la función
no cambiara el valor del parámetro. Por ejemplo, la siguiente función
usa este concepto:
char *strcpy(char *dest, const char *orig);
El segundo argumento orig
es una cadena de C que no será alterada, cuando se use la función de la biblioteca para copiar cadenas.
Lo mismo que en otros lenguajes de programación, en C se tienen los
operadores aritméticos más usuales (+
suma, -
resta,
*
multiplicación, /
división y %
módulo).
El operador de asignación es =
, por ejemplo: i=4; ch='y';
Incremento ++
y decremento --
unario. Los cuales son más eficientes que las respectivas asignaciones. Por ejemplo: x++
es más rápido que x=x+1
.
Los operadores ++
y --
pueden ser
prefijos o postfijos. Cuando son prefijos, el valor es calculado antes
de que la expresión sea evaluada, y cuando es postfijo el valor es
calculado después que la expresión es evaluada.
En el siguiente ejemplo, ++z
es prefijo y --
es postfijo:
int x,y,z; main() { x=( ( ++z ) - ( y-- ) ) % 100; }
Que es equivalente a:
int x,y,z; main() { z++; x = ( z-y ) % 100; y--; }
El operador %
(módulo o residuo) solamente trabaja con enteros, aunque existe una función para flotantes (15.1 fmod()
) de la biblioteca matemática.
El operador división /
es para división entera y flotantes. Por lo
tanto hay que tener cuidado. El resultado de x = 3 / 2;
es uno, aún
si x
es declarado como float. La regla es: si ambos argumentos en una
división son enteros, entoces el resultado es entero. Si se desea obtener la
división con la fracción, entonces escribirlo como: x = 3.0 / 2;
o
x = 3 / 2.0
y aún mejor x = 3.0 / 2.0
.
Por otra parte, existe una forma más corta para expresar cálculos en C.
Por ejemplo, si se tienen expresiones como: i = i + 3;
o x = x * (y + 2);
, pueden ser reescritas como:
Lo cual es equivalente, pero menos eficiente que:
Por lo que podemos reescribir las expresiones anteriores como: i += 3;
y x *= y + 2;
respectivamente.
El operador para probar la igualdad es ==
, por lo que se deberá tener
cuidado de no escribir accidentalmente sólo =
, ya que:
if ( i = j ) ...
Es una sentencia legal de C (sintácticamente hablando aunque el compilador
avisa cuando se emplea), la cual copia el
valor de ``j
'' en ``i
'', lo cual será interpretado como
VERDADERO, si j
es diferente de cero.
Diferente es !=
, otros operadores son: <
menor que, >
mayor que, <=
menor que o igual a y >=
(mayor que o igual a).
Los operadores lógicos son usualmente usados con sentencias condicionales o relacionales, los operadores báscios lógicos son:
&&
Y lógico, ||
O lógico y !
negación.
Es necesario ser cuidadosos con el significado de expresiones tales como
a + b * c
, dependiendo de lo que se desee hacer
(a + b) * c
o
a + (b * c)
Todos los operadores tienen una prioridad, los operadores de mayor prioridad son evaluados antes que los que tienen menor prioridad. Los operadores que tienen la misma prioridad son evaluados de izquierda a derecha, por lo que:
a - b - c
es evaluado como
(a - b) - c
Prioridad | Operador(es) |
---|---|
Más alta | ( ) [ ] -> |
! ~ ++ -- - (tipo) *
& sizeof |
|
* / % |
|
+ - |
|
<< >> |
|
< <= > >= |
|
== != |
|
& |
|
^ |
|
| |
|
&& |
|
|| |
|
? |
|
= += -= *= /= |
|
Más baja | , |
De acuerdo a lo anterior, la siguiente expresión:
a < 10 && 2 * b < c
Es interpretada como:
(a < 10) && ( (2 * b) < c )
y
a = b = 10 / 5 + 2;
como
a = ( b = ( 10 / 5 ) + 2 );
Escribir programas en C para hacer las siguientes tareas:
100.0 grados Celsius son 212.0 grados Fahrenheit.