SlideShare una empresa de Scribd logo
1 de 40
Descargar para leer sin conexión
Introducción a la
programación en
    lenguaje C
Introducción


C es un lenguaje de programación de propósito general que ofrece economía sintáctica,
control de flujo y estructuras sencillas y un buen conjunto de operadores. No es un lenguaje
de muy alto nivel y más bien un lenguaje pequeño, sencillo y no está especializado en ningún
tipo de aplicación. Esto lo hace un lenguaje potente, con un campo de aplicación ilimitado y
sobre todo, se aprende rápidamente. En poco tiempo, un programador puede utilizar la
totalidad del lenguaje.
Este lenguaje ha sido estrechamente ligado al sistema operativo UNIX, puesto que fueron
desarrollados conjuntamente. Sin embargo, este lenguaje no está ligado a ningún sistema
operativo ni a ninguna máquina concreta. Se le suele llamar lenguaje de programación de
sistemas debido a su utilidad para escribir compiladores y sistemas operativos, aunque de
igual forma se pueden desarrollar cualquier tipo de aplicación.
La base del C proviene del BCPL, escrito por Martin Richards, y del B escrito por Ken
Thompson en 1970 para el primer sistema UNIX en un DEC PDP-7. Estos son lenguajes sin
tipos, al contrario que el C que proporciona varios tipos de datos. Los tipos son caracteres,
números enteros y en coma flotante, de varios tamaños. Además se pueden crear tipos
derivados mediante la utilización de punteros, vectores, registros y uniones. El primer
compilador de C fue escrito por Dennis Ritchie para un DEC PDP-11 y escribió el propio
sistema operativo en C.
C trabaja con tipos de datos que son directamente tratables por el hardware de la mayoría
de computadoras actuales, como son los caracteres, números y direcciones. Estos tipos de
datos pueden ser manipulados por las operaciones aritméticas que proporcionan las
computadoras. No proporciona mecanismos para tratar tipos de datos que no sean los
básicos, debiendo ser el programador el que los desarrolle. Esto permite que el código
generado sea muy eficiente y de ahí el éxito que ha tenido como lenguaje de desarrollo de
sistemas. No proporciona otros mecanismos de almacenamiento de datos que no sea el
estático y no proporciona mecanismos de entrada ni salida. Ello permite que el lenguaje
sea reducido y los compiladores de fácil implementación en distintos sistemas. Por contra,
estas carencias se compensan mediante la inclusión de funciones de librería para realizar
todas estas tareas, que normalmente dependen del sistema operativo.

Originariamente, el manual de referencia del lenguaje para el gran público fue el libro [1] de
Kernighan y Ritchie, escrito en 1977. Es un libro que explica y justifica totalmente el
desarrollo de aplicaciones en C, aunque en él se utilizaban construcciones, en la definición
de funciones, que podían provocar confusión y errores de programación que no eran
detectados por el compilador. Como los tiempos cambian y las necesidades también, en
1983 ANSI establece el comité X3J11 para que desarrolle una definición moderna y
comprensible del C. El estándar está basado en el manual de referencia original de 1972 y
se desarrolla con el mismo espíritu de sus creadores originales. La primera versión de
estándar se publicó en 1988 y actualmente todos los compiladores utilizan la nueva
definición. Una aportación muy importante de ANSI consiste en la definición de un conjunto
de librerías que acompañan al compilador y de las funciones contenidas en ellas. Muchas
de las operaciones comunes con el sistema operativo se realizan a través de estas
funciones. Una colección de ficheros de encabezamiento, headers, en los que se definen
los tipos de datos y funciones incluidas en cada librería.
Los programas que utilizan estas bibliotecas para interactuar con el sistema operativo
obtendrán un comportamiento equivalente en otro sistema.
Programas
La mejor forma de aprender un lenguaje es programando con él. El programa más sencillo
que se puede escribir en C es el siguiente:
main()
{




}


Como nos podemos imaginar, este programa no hace nada, pero contiene la parte más
importante de cualquier programa C y además, es el más pequeño que se puede escribir y
que se compile correctamente. En el se define la función main, que es la que ejecuta el
sistema operativo al llamar a un programa C. El nombre de una función C siempre va
seguida de paréntesis, tanto si tiene argumentos como si no. La definición de la función está
formada por un bloque de sentencias, que esta encerrado entre llaves {}.
Forma general de un programa en C
 declaraciones globales
  main ()
  {
          Variables locales
          secuencia de sentencias
  }
  f1 ()
      {
          Variables locales
          Secuencia de sentencias
      }
  .
  fn ()
  {
          Variables locales
          Secuencia de sentencias
      }
Un programa algo más complicado pero que hace algo, es el siguiente:


#include <stdio.h>
main()
{
printf("Hola amigos!n");
}


Con el visualizamos el mensaje Hola amigos! en el terminal. En la primera línea indica
que se tengan en cuenta las funciones y tipos definidos en la librería stdio (standard
input/output). Estas definiciones se encuentran en el fichero header stdio.h. Ahora, en la
función main se incluye una única sentencia que llama a la función printf. Esta toma como
argumento una cadena de caracteres, que se imprimen van encerradas entre dobles comillas
" ". El símbolo n indica un cambio de línea. Hay un grupo de símbolos, que son tratados
como caracteres individuales, que especifican algunos caracteres especiales del código
ASCII. Los más importantes son:
a       alert
b                       backspace
f                       formfeed
n                       newline
r                       carriage return
t                       horizontal tab
v                     vertical tab
                       backslash
‘                       single quote
“                     double quote
OOO             visualiza un carácter cuyo código ASCII es OOO en octal.
xHHH   visualiza un carácter cuyo código ASCII es HHH en hexadecimal.
El desarrollo de un programa


Un programa C puede estar formado por diferentes módulos o fuentes. Es conveniente
mantener los fuentes de un tamaño no muy grande, para que la compilación sea rápida.
También, al dividirse un programa en partes, puede facilitar la legibilidad del programa y su
estructuración. Los diferentes fuentes son compilados de forma separada, únicamente los
fuentes que han sido modificados desde la última compilación, y después combinados con
las librerías necesarias para formar el programa en su versión ejecutable.
Los comandos necesarios para compilar, linkar y ejecutar un programa dependen del
sistema operativo y debemos dirigirnos a los manuales correspondientes para conocer la
sintaxis exacta. Como forma más común podemos dar la siguiente:


cc prog
cc modulo1, modulo2
link prog, modulo1, modulo2
prog
Un mapa conceptual de la memoria para un programa en C
                                     Un programa compilado en C crea y
                                     usa cuatro regiones de memoria
                                     lógicas diferentes que sirven para
                                     funciones específicas. La primera
                                     región es la memoria que contiene
               Pila                  realmente el código del programa. La
                                     siguiente región es la memoria donde
                                     se guardan las variables globales.
              Montón                 Las dos regiones restantes son la pila
                                     ( en inglés, STACK ) y el montón ( en
                                     inglés, HEAP ). La pila se usa para
         Variables Globales          muchas cosas durante la ejecución
                                     del     programa.     Mantiene     las
                                     direcciones de vuelta para las
                                     llamadas a funciones, así como las
         Código de programa          variables locales. También sirve para
                                     salvar el estado de la CPU. El
                                     montón es la región de memoria libre
                                     que puede usar el programa
                                     mediante las funciones de asignación
                                     dinámicas para cosas las listas
                                     enlazadas y los árboles.
Proceso de compilación
Los términos que siguen se usarán frecuentemente a lo largo de este material :


Código Fuente      : El texto de un programa que un usuario puede leer; normalmente
considerado como el programa. El código fuente es la entrada al compilador de C.
Código Objeto : La traducción del código fuente de un programa a código de máquina, que
es el que el computador puede leer y ejecutar directamente. El código objeto es la entrada al
enlazador.
Enlazador : Un programa que enlaza funciones compiladas por separado para producir un
solo programa. Combina las funciones de la biblioteca estándar de C con el código que se ha
escrito. La salida del enlazador es un programa ejecutable.
Biblioteca : El archivo que contiene las funciones estándar que se pueden usar en los
programas. Las funciones incluyen todas las operaciones de E/S, así como otras rutinas
útiles.
Tiempo de Compilación : Lo que sucede mientras un programa es compilado. Algo que
ocurre con frecuencia durante el tiempo de compilación es un error de sintaxis.
Tiempo de ejecución : Lo que sucede mientras un programa es ejecutado.
Nombres de identificadores
Los nombres usados para referirse a las variables, las funciones, las etiquetas y otros
objetos definidos por el usuario se conocen como Identificadores. La longitud de un
identificador en C puede variar entre uno y treinta dos caracteres. El primer carácter debe
ser una letra o un símbolo de subrayado ( guión bajo “_ “ ) y los caracteres siguientes
pueden ser letras, números o símbolos de subrayados. El lenguaje C también permite usar
el símbolo $ en un nombre de identificador, pero no se trata de algo estándar, siendo
recomendable no hacerlo. A continuación se muestran algunos nombres de identificadores
correctos e incorrectos.


        Correctos                                         Incorrectos


         cont                                               1cont
         prueba23                                           Hola!
         balance_total                                      balance..total


En C las minúsculas y las mayúsculas se tratan como distintas. Así, cuenta, Cuenta y
CUENTA son tres identificadores distintos. Un identificador no puede ser igual que una
palabra clave del lenguaje y no debe tener el mismo nombre que alguna función ya escrita o
que se encuentre en la biblioteca del lenguaje.
Tipos básicos y variables


Los tipos de datos básicos definidos por C son caracteres, números enteros y números en
coma flotante. Los caracteres son representados por char, los enteros por short, int,
long y los números en coma flotante por float y double. Los tipos básicos disponibles y
su tamaño son:


char         Carácter                                  (normalmente 8 bits)
short         Entero corto con signo                    (normalmente 16 bits)
int          Entero con signo                          (depende de la implementación)
unsigned      Entero sin signo                          (depende de la implementación)
long         Entero largo con signo                    (normalmente 32 bits)
float         Flotante simple                           (normalmente 32 bits)
double       Flotante doble                             (normalmente 64 bits)


La palabra unsigned en realidad es un modificador aplicable a tipos enteros, aunque si no
se especifica un tipo se supone int. Un modificador es una palabra clave de C que indica
que una variable, o función, no se comporta de la forma normal. Hay también un modificador
signed, pero como los tipos son por defecto con signo, casi no se utiliza.
Tamaños y rangos de los tipos de datos básicos


Tipo                            Tamaño en Bits                         Rango


char                                 8                               0 a 255
int                                 16                             -32.768 a 32.767
float                               32                             3,4E-38 a 3,4E +38
double                              64                         1,7E –308 a 1,7E+308
void                                 0                             sin valor
Los valores del tipo char se usan normalmente para guardar valores definidos el juego de
caracteres ASCII, así como cualquier cantidad de 8 bits. Las variables de int se usan para
guardar cantidades enteras. Las variables de tipo float o double se usan para guardar
números reales.
El tipo void tiene tres usos.
           - declarar explícitamente una función como que no devuelve valor alguno.
           - declarar explícitamente una función sin parámetros.
           - para crear punteros genéricos.
Modificadores de tipos
A excepción del tipo void, los tipos de datos básicos pueden tener distintos modificadores
precediéndolos. Un modificador se usa para alterar el significado del tipo base para que se
ajuste más precisamente a las necesidades de cada momento. A continuación se muestra la
lista de modificares :
          signed
          unsigned
          long
          short
Los modificadores signed, unsigned, short y long se pueden aplicar a los tipos base entero y
de carácter. Sin embargo, long también se puede aplicar a double. El uso de signed en
enteros es redundante ( pero admisible ).
La diferencia entre enteros con y sin signo está en cómo se interpreta el bit más significativo
del entero. Si se especifica un entero con signo, el compilador genera código que asume que
el bit más significativo va ser usado como un indicador de signo. Si el indicador de signo es 0,
entonces el número es positivo; si es un 1, el número es negativo. Por ejemplo
 127 en binario es            00000000 01111111
-127 en binario es            10000000 01111111
Todas las combinaciones de los tipos básicos y los modificadores en C


Tipo                  Tamaño en Bits              Rango
char                     8                        -128 a 127
unsigned char             8                        0 a 255
signed char               8                        -128 a 127
int                      16                        -32.768 a 32.767
unsigned int             16                        0 a 65535
signed int               16                        -32.768 a 32.767
short int                16                        -32.768 a 32.767
unsigned short int        16                        0 a 65535
signed short int          16                       -32.768 a 32.767
long int                  32                       -2147483648 a 2147483648
signed long int           32                       -2147483648 a 2147483648
float                    32                        3,4E-38 a 3,4E+38
double                    64                       1,7E-308 a 1,7E+308
long double               64                       1,7E-308 a 1,7E+308
Declaración de variables
Todas las variables han de ser declaradas antes de poder ser usadas. La forma general de
declaración es la que se muestra a continuación :
tipo lista_de_variables;
Aquí, tipo debe ser un tipo válido de C y la lista_de_variables puede consistir en uno o más
nombres de identificadores separados por comas. A continuación se muestran algunas
declaraciones :
int i, j, l ;
short int si ;
unsigned int ui ;
double balance, beneficio, pérdida ;
Hay que tener claro que en C el nombre de una variable no tiene nada que ver con su tipo.
Existen tres sitios básicos donde se pueden declarar variables: dentro de las funciones, en la
definición de parámetros de funciones y fuera de todas las funciones.
Estas variables son, respectivamente, las variables locales, los parámetros formales y las
variables globales.
Variables Locales
Las variables que se declaran dentro de una función se denominan variables locales. En
algunos libros de C, estas variables se denominan automáticas, debido a que en C se
pueden usar la palabra clave ( opcional ) auto para declararlas. Dado que el término variable
local es el más común, es lo que usaremos para su identificación. Las variables locales
pueden ser denominadas sólo por sentencias que estén dentro del bloque en el que han sido
declaradas. O dicho de otra forma, las variables locales no son conocidas fuera de su propio
bloque de código. Recordar que un bloque de código comienza con una llave abierta y
termina con una llave cerrada.
Una de las cosas más importantes que hay que comprender sobre las variables locales es
que solo existen mientras se está ejecutando el bloque de código en el que son declaradas.
O sea, la variable local se crea al entrar en el bloque y se destruye al salir de él.
El bloque de código más normal en el que se declaran variables locales es la función. Por
ejemplo :
  void func1 ( void )                           void func2 ( void)
   {                                             {
       int x ;                                       int x ;
       x = 10 ;                                       x = -199 ;
   }                                             }
La variable entera x se declara dos veces, una vez en func1() y otra en func2(). La x de
func1() no corresponde ni tiene relación con la x de func2(). La razón es que cada x sólo es
conocida en el propio código en que se ha declarado la variable.
La mayoría de los programadores declaran todas las variables que se necesitan en una
función al principio del bloque de código de la misma. Esto se hace así para que sea más fácil
al leer el código saber qué variables se usan. Sin embargo, no es necesario hacerlo así, ya
que se pueden declarar variables locales en cualquier bloque de código. Para comprender
cómo funciona esto, considere la siguiente función :
Void f( void)
{
    int t ;
    scanf( “%d”, &t );
    if ( t== 1 ) {
                   char s[80]; /* esta se crea sólo al entrar en este bloque */
        printf(“introduzca el nombre : “ );
        gets(s);
        procesar (s) ;
    }
                   /* aquí no se conoce a s */
}
Aquí, la variable local s se crea tras entrar en el bloque de código if y se destruye tras salir
de él. Más aún s sólo es conocida dentro del bloque if y no puede ser denominada en
ninguna parte fuera de él.
Dado que las variables locales se crean y se destruyen cada vez que se entra o se sale de la
función en la que son declaradas, no pueden retener sus valores entre llamadas. ( Sin
embargo, es posible indicar al compilador que retenga sus valores mediante el uso del
modificador static ).

Parámetros formales
Si una función va a usar argumentos, debe declarar las variables que van a aceptar los
valores de los argumentos. Estas variables son los parámetros formales de la función.
Se comportan como cualquier otra variable local de la función. Como se muestra en el
siguiente fragmento de programa, sus declaraciones se dan tras el nombre de la función y
entre paréntesis.
/* Devuelve 1 si c es parte de la cadena s; sino 0 */
Esta_en( char *s, char c)
{
    while (*s)
       if (*s == c ) return 1 ;
       else s++ ;
    return 0 ;
}
La función esta_en() tiene dos argumentos s y c. Se debe indicar al compilador de C qué tipo
de variables son los parámetros formales, haciéndolo tal como se ha mostrado. Una vez que
se ha hecho, pueden ser usadas dentro de la función como variables locales normales. Al igual
que las variables locales, también son dinámicas y se destruyen al salir de la función.
Hay que asegurar que los parámetros formales que se declaran sean del mismo tipo que los
argumentos que se usan en la llamada a la función. Si existe una diferencia de tipo, se pueden
dar unos resultados inesperados. A diferencia de otros lenguajes, C es muy robusto y
normalmente siempre hace algo, incluso aunque no sea lo que se desea. Hay muy pocos
errores en tiempo de ejecución y no se comprueban los límites. Como programador, hay que
asegurar de que no se den errores de inconsistencia de tipos.
Al igual que con las variables locales, se pueden hacer asignaciones a los parámetros
formales de una función o usarlos en cualquier expresión válida en C. Aunque esas variables
reciben sus valores de los argumentos pasados a la función, se pueden usar como cualquier
otra variable local.

Variables Globales
A diferencia de las variables locales, las variables globales se conocen a lo largo de todo el
programa y se pueden usar en cualquier parte del código. Además, mantienen su valor durante
toda la ejecución del programa. Las variables globales se crean al declararlas en cualquier
parte fuera de una función. Pueden ser accedidas por cualquier expresión independientemente
de la función en la que se encuentre la expresión.
En el programa que sigue se puede ver que la variable cuenta ha sido declarada fuera de
todas las funciones. Aunque se declaración aparece antes de la función main(), se podría
haber colocado en cualquier lugar anterior a su primer uso, mientras no sea en una función.
Sin embargo, lo mejor es declarar todas las variables globales al principio del programa.
# include <stdio.h>
void func1 ( void), func2(void);
int cuenta; /* cuenta es global */
main ( void )
{
    cuenta = 100 ;
    func1() ;
    return 0;   /* comunicar el éxito al programa */
}
void func1 ( void )                                        void func2 ( void )
{                                                      {
    int temp;                                               int cuenta;
    temp = cuenta ;                                         for ( cuenta = 1; cuenta <10; cuenta++)
    func2() ;                                                   putchar(‘_’) ;
    printf( “cuentas es %d”, cuenta );                 }
}
Observando detenidamente este programa, debe estar claro que aunque ni main() ni func1()
han declarado la variable cuenta, ambas pueden usarla. Sin embargo, la func2() declara una
variable local llamada cuenta. Cuando func2() hace referencia a cuenta, sólo hace referencia
a su variable local, no a la global. Si una variable global y una variable local tienen el mismo
nombre, todas las referencias a ese nombre de variable dentro de la función donde se ha
declarado la variable local se refieren a esa variable local y no tienen efecto sobre la variable
global. Esto es algo conveniente. Sin embargo, si se olvida, el programa puede actuar de
forma extraña, incluso aunque “ parezca “ correcto.
El almacenamiento de las variables globales se hace en una región de memoria fija
establecida para este propósito por el compilador. Las variables globales son muy útiles
cuando se usan los mismos datos en varias funciones del programa. Sin embargo, se debe
evitar el uso de variables globales innecesarias, por tres razones :
1.- Utilizan memoria todo el tiempo de ejecución del programa, no solo cuando se necesitan.
2.- El uso de una variable global cuando se podría usar una variable local hace que la
función sea menos general debido a que depende de algo que debe estar definido fuera de
ella.
3.- El uso de un gran número de variables globales puede producir errores en el programa
debido a efectos secundarios desconocidos y no deseables.
Por ejemplo, a continuación se muestran dos formas de escribir mul () – una sencilla función
que calcula el producto de dos enteros .


General                                                     Espeficica


mul ( inte x, int y )                          int x, y ;
{                                              mul ( void )
    return ( x * y )                           {
}                                                    return ( x * Y )
                                                }
Ambas funciones devuelven el producto de las variables x e y. Sin embargo, la versión
generalizada, o parametrizada, se puede usar para devolver el producto de cualesquiera dos
enteros, mientras que la versión específica sólo se puede usar para calcular el producto de
las variables globales x e y.
Las variables son definidas utilizando un identificador de tipo seguido del nombre de la
variable. Veamos el siguiente programa.
#include <stdio.h>
main()
{
float cels, farh;
              farh = 35.0;
              cels = 5.0 * ( farh - 32.0 ) / 9.0;
              printf(">>> %f F son %f Cn", farh, cels );
}


En el programa anterior se definen dos variables float, se asigna un valor a la primera y
se calcula la segunda mediante una expresión aritmética. Las asignaciones en C también
son una expresión, por lo que se pueden utilizar como parte de otra expresión, pero según
que prácticas de este tipo no son muy recomendables ya que reducen la legibilidad del
programa. En la instrucción printf, el símbolo %f indica que se imprime un número en
coma flotante.
Hay un tipo muy importante que se representa por void que puede significar dos cosas
distintas, según su utilización. Puede significar nada, o sea que si una función devuelve un
valor de tipo void no devuelve ningún resultado, o puede significar cualquier cosa, como
puede ser un puntero a void es un puntero genérico a cualquier tipo de dato. Más adelante
veremos su utilización.

Funciones
Un programa C está formado por un conjunto de funciones que al menos contiene la función
main. Una función se declara con el nombre de la función precedido del tipo de valor que
retorna y una lista de argumentos encerrados entre paréntesis. El cuerpo de la función está
formado por un conjunto de declaraciones y de sentencias comprendidas entre llaves.
Veamos un ejemplo de utilización de funciones:
#include <stdio.h>                int fact_r ( int v )
    #define VALOR 5               {
#define FACT 120                      if ( v == 0 )
int fact_i ( int v )                                  return 1;
{                                     else
         int r = 1, i = 0;                            return v *
                                  fact_r(v-1);
         while ( i <= v ) {
                                      }
                     r = r * i;
                     i = i + 1;
           }
        return r;
    }
main()
{
    int r, valor = VALOR;
    if ( (r = fact_i(valor)) != fact_r(valor) )
                       printf("Codificación errónea!!.n");
    else
             if ( r == FACT )
                           printf("Codificación correcta.n");
             else
                            printf("Algo falla!!.n");
    }
Se definen dos funciones, fact_i y fact_r, además de la función main. Ambas toman
como parámetro un valor entero y devuelven otro entero. La primera calcula el factorial de un
número de forma iterativa, mientras que la segunda hace lo mismo de forma recursiva.
Todas las líneas que comienzan con el símbolo # indican una directiva del precompilador.
Antes de realizar la compilación en C se llama a un precompilador cuya misión es procesar el
texto y realizar ciertas sustituciones textuales. Hemos visto que la directiva #include incluye
el texto contenido en un fichero en el fuente que estamos compilando. De forma parecida,
#define nombre texto sustituye todas las apariciones de nombre por texto. Así, en el fuente,
la palabra VALOR se sustituye por el número 5.
El valor que debe devolver una función se indica con la palabra return. La evaluación de la
expresión debe dar una valor del mismo tipo de dato que el que se ha definido como
resultado. La declaración de una variable puede incluir una inicialización en la misma
declaración. Se debe tener muy en cuenta que en C todos los argumentos son pasados 'por
valor'. No existe el concepto de paso de parámetros 'por variable' o 'por referencia'.
Veamos un ejemplo:
int incr ( int v )
                                          main()
{
                                           {
      return v + 1;
                                           int a, b; b = 3;
}
                                           a = incr(b);
                                           /*
                                                a = 4 mientras que
                                             b = 3. No ha cambiado después de
                                          la llamada.
                                          */
                                           }



    En el ejemplo anterior el valor del parámetro de la función incr, aunque se modifique
    dentro de la función, no cambia el valor de la variable b de la función main. Todo el
    texto comprendido entre los caracteres /* y */ son comentarios al programa y son
    ignorados por el compilador. En un fuente C los comentarios no se pueden anidar.
Expresiones y operadores
Los distintos operadores permiten formar expresiones tanto aritméticas como lógicas. Los
operadores aritméticos y lógicos son:


+, -                     suma, resta
++, --                    incremento, decremento
*, /, %                  multiplicación, división, módulo
>>, <<                  rotación de bits a la derecha, izquierda.
&                       AND booleano
|                        OR booleano
^                        EXOR booleano
~                        complemento a 1
!                        complemento a 2, NOT lógico
==, !=                    igualdad, desigualdad
&&, ||                    AND, OR lógico
<, <=                    menor, menor o igual
>, >=                    mayor, mayor o igual
En estos operadores deben tenerse en cuenta la precedencia de operadores y las reglas de
asociatividad, que son las normales en la mayoría de lenguajes. Se debe consultar el manual
de referencia para obtener una explicación de tallada. Además hay toda una serie de
operadores aritméticos con asignación, como pueden ser += y ^=.
En la evaluación de expresiones lógicas, los compiladores normalmente utilizan técnicas de
evaluación rápida. Para decidir si una expresión lógica es cierta o falsa muchas veces no es
necesario evaluarla completamente. Por ejemplo una expresión formada <exp1> || <exp2>,
el compilador evalúa primero <exp1> y si es cierta, no evalúa <exp2>. Por ello se deben
evitar construcciones en las que se modifiquen valores de datos en la propia expresión, pues
su comportamiento puede depender de la implementación del compilador o de la
optimización utilizada en una compilación o en otra. Estos son errores que se pueden
cometer fácilmente en C ya que una asignación es también una expresión.


Debemos evitar:
    if (( x++ > 3 ) || ( x < y ))
y escribir en su lugar:
    x++;
    if (( x > 3 ) || ( x < y ))
Hay un tipo especial de expresión en C que se denomina expresión condicional y está
representada por los operadores ? : . Su utilización es como sigue: <e> ? <x> : <y>. Se
evalúa si e entonces x; si no, y.
int mayor ( int a, int b )
{
       return ( a > b ) ? TRUE : FALSE;
}
waste_time ()
{
float a, b = 0.0;
( b > 0.0 ) ? sin(M_PI / 8) : cos(M_PI / 4);
}
Conversión de tipos
Cuando escribimos una expresión aritmética a+b, en la cual hay variables o valores de
distintos tipos, el compilador realiza determinadas conversiones antes de que evalúe la
expresión. Estas conversiones pueden ser para 'aumentar' o 'disminuir' la precisión del tipo al
que se convierten los elementos de la expresión. Un ejemplo claro, es la comparación de una
variable de tipo int con una variable de tipo double. En este caso, la de tipo int es
convertida a double para poder realizar la comparación.
Los tipos pequeños son convertidos de la forma siguiente: un tipo char se convierte a int,
con el modificador signed si los caracteres son con signo, o unsigned si los caracteres son
sin signo. Un unsigned char es convertido a int con los bits más altos puestos a cero. Un
signed char es convertido a int con los bits más altos puestos a uno o cero, dependiendo
del valor de la variable.
Para los tipos de mayor tamaño: si un operando es de tipo double, el otro es convertido a
double. Si un operando es de tipo float, el otro es convertido a float. Si un operando es
de tipo unsigned long, el otro es convertido a unsigned long. Si un operando es de tipo
long, el otro es convertido a long. Si un operando es de tipo unsigned, el otro es convertido
a unsigned. Si no, los operandos son te tipo int.
Una variable o expresión de un tipo se puede convertir explícitamente a otro tipo,
anteponiéndole el tipo entre paréntesis.


cambio_tipo ()
{
float a;
int b;
b = 10;
a = 0.5;
if ( a <= (float) b )
           menor();
}
Control de flujo.


La sentencia de control básica es if (<e>) then <s> else <t>. En ella se evalúa una
expresión condicional y si se cumple, se ejecuta la sentencia s; si no, se ejecuta la
sentencia t. La segunda parte de la condición, else <t>, es opcional.


int cero ( double a )
{
      if ( a == 0.0 )
        return (TRUE);
      else
        return (FALSE);
}
En el caso que <e> no sea una expresión condicional y sea aritmética, se considera falso si
vale 0; y si no, verdadero. Hay casos en los que se deben evaluar múltiples condiciones y
únicamente se debe evaluar una de ellas. Se puede programar con un grupo de sentencias
if then else anidadas, aunque ello puede ser farragoso y de complicada lectura. Para
evitarlo nos puede ayudar la sentencia switch. Su utilización es:




switch (valor)
{
       case valor1: <sentencias>
       case valor2: <sentencias>
             ...
       default: <sentencias>
}
Cuando se encuentra una sentencia case que concuerda con el valor del switch se
ejecutan las sentencias que le siguen y todas las demás a partir de ahí, a no ser que se
introduzca una sentencia break para salir de la sentencia switch. Por ejemplo,


ver_opcion ( char c )
{
    switch(c)
    {
        case 'a':    printf("Op An");    break;
        case 'b':    printf("Op Bn");    break;
        case 'c':
        case 'd':    printf("Op C o Dn"); break;
        default: printf("Op ?n");
     }
}
Otras sentencias de control de flujo son las que nos permiten realizar iteraciones sobre un
conjunto de sentencias. En C tenemos tres formas principales de realizar iteraciones. La
sentencia while (<e>) <s> es seguramente la más utilizada. La sentencia, o grupo de
sentencias <s> se ejecuta mientras la evaluación de la expresión <e> sea verdadera.




long raiz ( long valor )
     {
             long r = 1;
             while ( r * r <= valor )
                           r++;
              return r;
         }
Otra sentencia iterativa, que permite inicializar los controles del bucle se la sentencia for
( <i>; <e>; <p> ) <s>. La sentencia for se puede escribir también como:


<i>;
while ( <e> )
{
<s>;
<p>;
}
El ejemplo anterior se podría escribir como:
long raiz ( long valor )
{
long r;
for ( r = 1; r * r <= valor; r++ ) ;
return r;
}

Más contenido relacionado

La actualidad más candente

Introduccion al lenguaje c
Introduccion al lenguaje cIntroduccion al lenguaje c
Introduccion al lenguaje cvictdiazm
 
Arquitecturas de ordenadores y compiladores cruzados
Arquitecturas de ordenadores y compiladores cruzadosArquitecturas de ordenadores y compiladores cruzados
Arquitecturas de ordenadores y compiladores cruzadosDIEGO BAROJA
 
Introduccion al-lenguaje-c
Introduccion al-lenguaje-cIntroduccion al-lenguaje-c
Introduccion al-lenguaje-cDalva Icaza
 
Trabajo compiladores ivan bolaños
Trabajo compiladores ivan bolañosTrabajo compiladores ivan bolaños
Trabajo compiladores ivan bolañosIván Bolaños
 
Lenguaje ensamblador
Lenguaje ensambladorLenguaje ensamblador
Lenguaje ensambladorDeisyVilchez
 
Programacion ensamblador-procesadoresk
Programacion ensamblador-procesadoreskProgramacion ensamblador-procesadoresk
Programacion ensamblador-procesadoreskJohann Chambilla
 
Historia de la programacion
Historia de la programacionHistoria de la programacion
Historia de la programacionTensor
 
Trabajo de compiladores completo alexandra
Trabajo de compiladores completo alexandraTrabajo de compiladores completo alexandra
Trabajo de compiladores completo alexandraAlexandraMolinaSanchez
 
Compiladores para fortran, pascal y c
Compiladores para fortran, pascal y cCompiladores para fortran, pascal y c
Compiladores para fortran, pascal y cLeonardo Lopez
 
Presentacion de la Unidad 2
Presentacion de la Unidad 2Presentacion de la Unidad 2
Presentacion de la Unidad 2Friasolan
 

La actualidad más candente (20)

Flex y bison
Flex y bisonFlex y bison
Flex y bison
 
Ensamblador
EnsambladorEnsamblador
Ensamblador
 
Introduccion al lenguaje c
Introduccion al lenguaje cIntroduccion al lenguaje c
Introduccion al lenguaje c
 
Arquitecturas de ordenadores y compiladores cruzados
Arquitecturas de ordenadores y compiladores cruzadosArquitecturas de ordenadores y compiladores cruzados
Arquitecturas de ordenadores y compiladores cruzados
 
Unmsm02 2008
Unmsm02 2008Unmsm02 2008
Unmsm02 2008
 
Programacion
ProgramacionProgramacion
Programacion
 
ENSAYO SOBRE EL LENGUAJE C
ENSAYO SOBRE EL LENGUAJE C ENSAYO SOBRE EL LENGUAJE C
ENSAYO SOBRE EL LENGUAJE C
 
Introduccion al-lenguaje-c
Introduccion al-lenguaje-cIntroduccion al-lenguaje-c
Introduccion al-lenguaje-c
 
Programacion
ProgramacionProgramacion
Programacion
 
Trabajo compiladores ivan bolaños
Trabajo compiladores ivan bolañosTrabajo compiladores ivan bolaños
Trabajo compiladores ivan bolaños
 
Lenguaje ensamblador
Lenguaje ensambladorLenguaje ensamblador
Lenguaje ensamblador
 
Lenguaje ensamblador
Lenguaje ensambladorLenguaje ensamblador
Lenguaje ensamblador
 
Lenguaje ensamblador
Lenguaje ensambladorLenguaje ensamblador
Lenguaje ensamblador
 
Programacion ensamblador-procesadoresk
Programacion ensamblador-procesadoreskProgramacion ensamblador-procesadoresk
Programacion ensamblador-procesadoresk
 
Historia de la programacion
Historia de la programacionHistoria de la programacion
Historia de la programacion
 
Trabajo de compiladores completo alexandra
Trabajo de compiladores completo alexandraTrabajo de compiladores completo alexandra
Trabajo de compiladores completo alexandra
 
Lenguaje Ensamblador
Lenguaje EnsambladorLenguaje Ensamblador
Lenguaje Ensamblador
 
Compiladores para fortran, pascal y c
Compiladores para fortran, pascal y cCompiladores para fortran, pascal y c
Compiladores para fortran, pascal y c
 
Presentacion de la Unidad 2
Presentacion de la Unidad 2Presentacion de la Unidad 2
Presentacion de la Unidad 2
 
Resumen1
Resumen1Resumen1
Resumen1
 

Similar a LENGUAJE en C

TEMA-2 Estructura de un programa en C.pptx
TEMA-2 Estructura de un programa en C.pptxTEMA-2 Estructura de un programa en C.pptx
TEMA-2 Estructura de un programa en C.pptxVctorEmmanuelEspinoM
 
Compilador e interpretador
Compilador e interpretadorCompilador e interpretador
Compilador e interpretadorFrancisco Leal
 
C ++ Estatutos ciclos
C ++ Estatutos ciclosC ++ Estatutos ciclos
C ++ Estatutos ciclosernest1960
 
Aplicacion de c
Aplicacion de cAplicacion de c
Aplicacion de chek_sk8
 
Compiladores, interpretadores y lenguajes de bajo, medio y alto nivel
Compiladores, interpretadores y lenguajes de bajo, medio y alto nivelCompiladores, interpretadores y lenguajes de bajo, medio y alto nivel
Compiladores, interpretadores y lenguajes de bajo, medio y alto nivelEstefhany1
 
CONOCIMIENTO DE PROGRAMACIÓN Y UN LENGUAJE ESTRUCTURADO
CONOCIMIENTO DE PROGRAMACIÓN Y UN LENGUAJE ESTRUCTURADOCONOCIMIENTO DE PROGRAMACIÓN Y UN LENGUAJE ESTRUCTURADO
CONOCIMIENTO DE PROGRAMACIÓN Y UN LENGUAJE ESTRUCTURADOadark
 
Presentación lenguaje c (pedro luis rodriguez c.i. 16388340)
Presentación lenguaje c (pedro luis rodriguez c.i. 16388340)Presentación lenguaje c (pedro luis rodriguez c.i. 16388340)
Presentación lenguaje c (pedro luis rodriguez c.i. 16388340)pedrolrc
 
Generalidades de la programacion
Generalidades de la programacionGeneralidades de la programacion
Generalidades de la programacionDiego Rojas
 

Similar a LENGUAJE en C (20)

TEMA-2 Estructura de un programa en C.pptx
TEMA-2 Estructura de un programa en C.pptxTEMA-2 Estructura de un programa en C.pptx
TEMA-2 Estructura de un programa en C.pptx
 
Compilador e interpretador
Compilador e interpretadorCompilador e interpretador
Compilador e interpretador
 
Informe lpi
Informe lpiInforme lpi
Informe lpi
 
Informe.
Informe.Informe.
Informe.
 
C ++ Estatutos ciclos
C ++ Estatutos ciclosC ++ Estatutos ciclos
C ++ Estatutos ciclos
 
Lenguaje C
Lenguaje CLenguaje C
Lenguaje C
 
Stephany diapositivas
Stephany diapositivasStephany diapositivas
Stephany diapositivas
 
Resumencap1 carmen vargas_jeremycamacho
Resumencap1 carmen vargas_jeremycamachoResumencap1 carmen vargas_jeremycamacho
Resumencap1 carmen vargas_jeremycamacho
 
Aplicacion de c
Aplicacion de cAplicacion de c
Aplicacion de c
 
Unidad 3
Unidad 3Unidad 3
Unidad 3
 
Compiladores, interpretadores y lenguajes de bajo, medio y alto nivel
Compiladores, interpretadores y lenguajes de bajo, medio y alto nivelCompiladores, interpretadores y lenguajes de bajo, medio y alto nivel
Compiladores, interpretadores y lenguajes de bajo, medio y alto nivel
 
CONOCIMIENTO DE PROGRAMACIÓN Y UN LENGUAJE ESTRUCTURADO
CONOCIMIENTO DE PROGRAMACIÓN Y UN LENGUAJE ESTRUCTURADOCONOCIMIENTO DE PROGRAMACIÓN Y UN LENGUAJE ESTRUCTURADO
CONOCIMIENTO DE PROGRAMACIÓN Y UN LENGUAJE ESTRUCTURADO
 
Presentación lenguaje c (pedro luis rodriguez c.i. 16388340)
Presentación lenguaje c (pedro luis rodriguez c.i. 16388340)Presentación lenguaje c (pedro luis rodriguez c.i. 16388340)
Presentación lenguaje c (pedro luis rodriguez c.i. 16388340)
 
Presentación1
Presentación1Presentación1
Presentación1
 
Presentación1
Presentación1Presentación1
Presentación1
 
Unidad 3
Unidad 3Unidad 3
Unidad 3
 
Unidad 3
Unidad 3Unidad 3
Unidad 3
 
Generalidades de la programacion
Generalidades de la programacionGeneralidades de la programacion
Generalidades de la programacion
 
Unidad 3
Unidad 3Unidad 3
Unidad 3
 
Unidad 3
Unidad 3Unidad 3
Unidad 3
 

LENGUAJE en C

  • 2. Introducción C es un lenguaje de programación de propósito general que ofrece economía sintáctica, control de flujo y estructuras sencillas y un buen conjunto de operadores. No es un lenguaje de muy alto nivel y más bien un lenguaje pequeño, sencillo y no está especializado en ningún tipo de aplicación. Esto lo hace un lenguaje potente, con un campo de aplicación ilimitado y sobre todo, se aprende rápidamente. En poco tiempo, un programador puede utilizar la totalidad del lenguaje. Este lenguaje ha sido estrechamente ligado al sistema operativo UNIX, puesto que fueron desarrollados conjuntamente. Sin embargo, este lenguaje no está ligado a ningún sistema operativo ni a ninguna máquina concreta. Se le suele llamar lenguaje de programación de sistemas debido a su utilidad para escribir compiladores y sistemas operativos, aunque de igual forma se pueden desarrollar cualquier tipo de aplicación. La base del C proviene del BCPL, escrito por Martin Richards, y del B escrito por Ken Thompson en 1970 para el primer sistema UNIX en un DEC PDP-7. Estos son lenguajes sin tipos, al contrario que el C que proporciona varios tipos de datos. Los tipos son caracteres, números enteros y en coma flotante, de varios tamaños. Además se pueden crear tipos derivados mediante la utilización de punteros, vectores, registros y uniones. El primer compilador de C fue escrito por Dennis Ritchie para un DEC PDP-11 y escribió el propio sistema operativo en C.
  • 3. C trabaja con tipos de datos que son directamente tratables por el hardware de la mayoría de computadoras actuales, como son los caracteres, números y direcciones. Estos tipos de datos pueden ser manipulados por las operaciones aritméticas que proporcionan las computadoras. No proporciona mecanismos para tratar tipos de datos que no sean los básicos, debiendo ser el programador el que los desarrolle. Esto permite que el código generado sea muy eficiente y de ahí el éxito que ha tenido como lenguaje de desarrollo de sistemas. No proporciona otros mecanismos de almacenamiento de datos que no sea el estático y no proporciona mecanismos de entrada ni salida. Ello permite que el lenguaje sea reducido y los compiladores de fácil implementación en distintos sistemas. Por contra, estas carencias se compensan mediante la inclusión de funciones de librería para realizar todas estas tareas, que normalmente dependen del sistema operativo. Originariamente, el manual de referencia del lenguaje para el gran público fue el libro [1] de Kernighan y Ritchie, escrito en 1977. Es un libro que explica y justifica totalmente el desarrollo de aplicaciones en C, aunque en él se utilizaban construcciones, en la definición de funciones, que podían provocar confusión y errores de programación que no eran detectados por el compilador. Como los tiempos cambian y las necesidades también, en 1983 ANSI establece el comité X3J11 para que desarrolle una definición moderna y comprensible del C. El estándar está basado en el manual de referencia original de 1972 y se desarrolla con el mismo espíritu de sus creadores originales. La primera versión de estándar se publicó en 1988 y actualmente todos los compiladores utilizan la nueva definición. Una aportación muy importante de ANSI consiste en la definición de un conjunto de librerías que acompañan al compilador y de las funciones contenidas en ellas. Muchas de las operaciones comunes con el sistema operativo se realizan a través de estas funciones. Una colección de ficheros de encabezamiento, headers, en los que se definen los tipos de datos y funciones incluidas en cada librería.
  • 4. Los programas que utilizan estas bibliotecas para interactuar con el sistema operativo obtendrán un comportamiento equivalente en otro sistema. Programas La mejor forma de aprender un lenguaje es programando con él. El programa más sencillo que se puede escribir en C es el siguiente: main() { } Como nos podemos imaginar, este programa no hace nada, pero contiene la parte más importante de cualquier programa C y además, es el más pequeño que se puede escribir y que se compile correctamente. En el se define la función main, que es la que ejecuta el sistema operativo al llamar a un programa C. El nombre de una función C siempre va seguida de paréntesis, tanto si tiene argumentos como si no. La definición de la función está formada por un bloque de sentencias, que esta encerrado entre llaves {}.
  • 5. Forma general de un programa en C declaraciones globales main () { Variables locales secuencia de sentencias } f1 () { Variables locales Secuencia de sentencias } . fn () { Variables locales Secuencia de sentencias }
  • 6. Un programa algo más complicado pero que hace algo, es el siguiente: #include <stdio.h> main() { printf("Hola amigos!n"); } Con el visualizamos el mensaje Hola amigos! en el terminal. En la primera línea indica que se tengan en cuenta las funciones y tipos definidos en la librería stdio (standard input/output). Estas definiciones se encuentran en el fichero header stdio.h. Ahora, en la función main se incluye una única sentencia que llama a la función printf. Esta toma como argumento una cadena de caracteres, que se imprimen van encerradas entre dobles comillas " ". El símbolo n indica un cambio de línea. Hay un grupo de símbolos, que son tratados como caracteres individuales, que especifican algunos caracteres especiales del código ASCII. Los más importantes son:
  • 7. a alert b backspace f formfeed n newline r carriage return t horizontal tab v vertical tab backslash ‘ single quote “ double quote OOO visualiza un carácter cuyo código ASCII es OOO en octal. xHHH visualiza un carácter cuyo código ASCII es HHH en hexadecimal.
  • 8. El desarrollo de un programa Un programa C puede estar formado por diferentes módulos o fuentes. Es conveniente mantener los fuentes de un tamaño no muy grande, para que la compilación sea rápida. También, al dividirse un programa en partes, puede facilitar la legibilidad del programa y su estructuración. Los diferentes fuentes son compilados de forma separada, únicamente los fuentes que han sido modificados desde la última compilación, y después combinados con las librerías necesarias para formar el programa en su versión ejecutable. Los comandos necesarios para compilar, linkar y ejecutar un programa dependen del sistema operativo y debemos dirigirnos a los manuales correspondientes para conocer la sintaxis exacta. Como forma más común podemos dar la siguiente: cc prog cc modulo1, modulo2 link prog, modulo1, modulo2 prog
  • 9. Un mapa conceptual de la memoria para un programa en C Un programa compilado en C crea y usa cuatro regiones de memoria lógicas diferentes que sirven para funciones específicas. La primera región es la memoria que contiene Pila realmente el código del programa. La siguiente región es la memoria donde se guardan las variables globales. Montón Las dos regiones restantes son la pila ( en inglés, STACK ) y el montón ( en inglés, HEAP ). La pila se usa para Variables Globales muchas cosas durante la ejecución del programa. Mantiene las direcciones de vuelta para las llamadas a funciones, así como las Código de programa variables locales. También sirve para salvar el estado de la CPU. El montón es la región de memoria libre que puede usar el programa mediante las funciones de asignación dinámicas para cosas las listas enlazadas y los árboles.
  • 11. Los términos que siguen se usarán frecuentemente a lo largo de este material : Código Fuente : El texto de un programa que un usuario puede leer; normalmente considerado como el programa. El código fuente es la entrada al compilador de C. Código Objeto : La traducción del código fuente de un programa a código de máquina, que es el que el computador puede leer y ejecutar directamente. El código objeto es la entrada al enlazador. Enlazador : Un programa que enlaza funciones compiladas por separado para producir un solo programa. Combina las funciones de la biblioteca estándar de C con el código que se ha escrito. La salida del enlazador es un programa ejecutable. Biblioteca : El archivo que contiene las funciones estándar que se pueden usar en los programas. Las funciones incluyen todas las operaciones de E/S, así como otras rutinas útiles. Tiempo de Compilación : Lo que sucede mientras un programa es compilado. Algo que ocurre con frecuencia durante el tiempo de compilación es un error de sintaxis. Tiempo de ejecución : Lo que sucede mientras un programa es ejecutado.
  • 12. Nombres de identificadores Los nombres usados para referirse a las variables, las funciones, las etiquetas y otros objetos definidos por el usuario se conocen como Identificadores. La longitud de un identificador en C puede variar entre uno y treinta dos caracteres. El primer carácter debe ser una letra o un símbolo de subrayado ( guión bajo “_ “ ) y los caracteres siguientes pueden ser letras, números o símbolos de subrayados. El lenguaje C también permite usar el símbolo $ en un nombre de identificador, pero no se trata de algo estándar, siendo recomendable no hacerlo. A continuación se muestran algunos nombres de identificadores correctos e incorrectos. Correctos Incorrectos cont 1cont prueba23 Hola! balance_total balance..total En C las minúsculas y las mayúsculas se tratan como distintas. Así, cuenta, Cuenta y CUENTA son tres identificadores distintos. Un identificador no puede ser igual que una palabra clave del lenguaje y no debe tener el mismo nombre que alguna función ya escrita o que se encuentre en la biblioteca del lenguaje.
  • 13. Tipos básicos y variables Los tipos de datos básicos definidos por C son caracteres, números enteros y números en coma flotante. Los caracteres son representados por char, los enteros por short, int, long y los números en coma flotante por float y double. Los tipos básicos disponibles y su tamaño son: char Carácter (normalmente 8 bits) short Entero corto con signo (normalmente 16 bits) int Entero con signo (depende de la implementación) unsigned Entero sin signo (depende de la implementación) long Entero largo con signo (normalmente 32 bits) float Flotante simple (normalmente 32 bits) double Flotante doble (normalmente 64 bits) La palabra unsigned en realidad es un modificador aplicable a tipos enteros, aunque si no se especifica un tipo se supone int. Un modificador es una palabra clave de C que indica que una variable, o función, no se comporta de la forma normal. Hay también un modificador signed, pero como los tipos son por defecto con signo, casi no se utiliza.
  • 14. Tamaños y rangos de los tipos de datos básicos Tipo Tamaño en Bits Rango char 8 0 a 255 int 16 -32.768 a 32.767 float 32 3,4E-38 a 3,4E +38 double 64 1,7E –308 a 1,7E+308 void 0 sin valor Los valores del tipo char se usan normalmente para guardar valores definidos el juego de caracteres ASCII, así como cualquier cantidad de 8 bits. Las variables de int se usan para guardar cantidades enteras. Las variables de tipo float o double se usan para guardar números reales. El tipo void tiene tres usos. - declarar explícitamente una función como que no devuelve valor alguno. - declarar explícitamente una función sin parámetros. - para crear punteros genéricos.
  • 15. Modificadores de tipos A excepción del tipo void, los tipos de datos básicos pueden tener distintos modificadores precediéndolos. Un modificador se usa para alterar el significado del tipo base para que se ajuste más precisamente a las necesidades de cada momento. A continuación se muestra la lista de modificares : signed unsigned long short Los modificadores signed, unsigned, short y long se pueden aplicar a los tipos base entero y de carácter. Sin embargo, long también se puede aplicar a double. El uso de signed en enteros es redundante ( pero admisible ). La diferencia entre enteros con y sin signo está en cómo se interpreta el bit más significativo del entero. Si se especifica un entero con signo, el compilador genera código que asume que el bit más significativo va ser usado como un indicador de signo. Si el indicador de signo es 0, entonces el número es positivo; si es un 1, el número es negativo. Por ejemplo 127 en binario es 00000000 01111111 -127 en binario es 10000000 01111111
  • 16. Todas las combinaciones de los tipos básicos y los modificadores en C Tipo Tamaño en Bits Rango char 8 -128 a 127 unsigned char 8 0 a 255 signed char 8 -128 a 127 int 16 -32.768 a 32.767 unsigned int 16 0 a 65535 signed int 16 -32.768 a 32.767 short int 16 -32.768 a 32.767 unsigned short int 16 0 a 65535 signed short int 16 -32.768 a 32.767 long int 32 -2147483648 a 2147483648 signed long int 32 -2147483648 a 2147483648 float 32 3,4E-38 a 3,4E+38 double 64 1,7E-308 a 1,7E+308 long double 64 1,7E-308 a 1,7E+308
  • 17. Declaración de variables Todas las variables han de ser declaradas antes de poder ser usadas. La forma general de declaración es la que se muestra a continuación : tipo lista_de_variables; Aquí, tipo debe ser un tipo válido de C y la lista_de_variables puede consistir en uno o más nombres de identificadores separados por comas. A continuación se muestran algunas declaraciones : int i, j, l ; short int si ; unsigned int ui ; double balance, beneficio, pérdida ; Hay que tener claro que en C el nombre de una variable no tiene nada que ver con su tipo. Existen tres sitios básicos donde se pueden declarar variables: dentro de las funciones, en la definición de parámetros de funciones y fuera de todas las funciones. Estas variables son, respectivamente, las variables locales, los parámetros formales y las variables globales.
  • 18. Variables Locales Las variables que se declaran dentro de una función se denominan variables locales. En algunos libros de C, estas variables se denominan automáticas, debido a que en C se pueden usar la palabra clave ( opcional ) auto para declararlas. Dado que el término variable local es el más común, es lo que usaremos para su identificación. Las variables locales pueden ser denominadas sólo por sentencias que estén dentro del bloque en el que han sido declaradas. O dicho de otra forma, las variables locales no son conocidas fuera de su propio bloque de código. Recordar que un bloque de código comienza con una llave abierta y termina con una llave cerrada. Una de las cosas más importantes que hay que comprender sobre las variables locales es que solo existen mientras se está ejecutando el bloque de código en el que son declaradas. O sea, la variable local se crea al entrar en el bloque y se destruye al salir de él. El bloque de código más normal en el que se declaran variables locales es la función. Por ejemplo : void func1 ( void ) void func2 ( void) { { int x ; int x ; x = 10 ; x = -199 ; } }
  • 19. La variable entera x se declara dos veces, una vez en func1() y otra en func2(). La x de func1() no corresponde ni tiene relación con la x de func2(). La razón es que cada x sólo es conocida en el propio código en que se ha declarado la variable. La mayoría de los programadores declaran todas las variables que se necesitan en una función al principio del bloque de código de la misma. Esto se hace así para que sea más fácil al leer el código saber qué variables se usan. Sin embargo, no es necesario hacerlo así, ya que se pueden declarar variables locales en cualquier bloque de código. Para comprender cómo funciona esto, considere la siguiente función : Void f( void) { int t ; scanf( “%d”, &t ); if ( t== 1 ) { char s[80]; /* esta se crea sólo al entrar en este bloque */ printf(“introduzca el nombre : “ ); gets(s); procesar (s) ; } /* aquí no se conoce a s */ }
  • 20. Aquí, la variable local s se crea tras entrar en el bloque de código if y se destruye tras salir de él. Más aún s sólo es conocida dentro del bloque if y no puede ser denominada en ninguna parte fuera de él. Dado que las variables locales se crean y se destruyen cada vez que se entra o se sale de la función en la que son declaradas, no pueden retener sus valores entre llamadas. ( Sin embargo, es posible indicar al compilador que retenga sus valores mediante el uso del modificador static ). Parámetros formales Si una función va a usar argumentos, debe declarar las variables que van a aceptar los valores de los argumentos. Estas variables son los parámetros formales de la función. Se comportan como cualquier otra variable local de la función. Como se muestra en el siguiente fragmento de programa, sus declaraciones se dan tras el nombre de la función y entre paréntesis. /* Devuelve 1 si c es parte de la cadena s; sino 0 */ Esta_en( char *s, char c) { while (*s) if (*s == c ) return 1 ; else s++ ; return 0 ; }
  • 21. La función esta_en() tiene dos argumentos s y c. Se debe indicar al compilador de C qué tipo de variables son los parámetros formales, haciéndolo tal como se ha mostrado. Una vez que se ha hecho, pueden ser usadas dentro de la función como variables locales normales. Al igual que las variables locales, también son dinámicas y se destruyen al salir de la función. Hay que asegurar que los parámetros formales que se declaran sean del mismo tipo que los argumentos que se usan en la llamada a la función. Si existe una diferencia de tipo, se pueden dar unos resultados inesperados. A diferencia de otros lenguajes, C es muy robusto y normalmente siempre hace algo, incluso aunque no sea lo que se desea. Hay muy pocos errores en tiempo de ejecución y no se comprueban los límites. Como programador, hay que asegurar de que no se den errores de inconsistencia de tipos. Al igual que con las variables locales, se pueden hacer asignaciones a los parámetros formales de una función o usarlos en cualquier expresión válida en C. Aunque esas variables reciben sus valores de los argumentos pasados a la función, se pueden usar como cualquier otra variable local. Variables Globales A diferencia de las variables locales, las variables globales se conocen a lo largo de todo el programa y se pueden usar en cualquier parte del código. Además, mantienen su valor durante toda la ejecución del programa. Las variables globales se crean al declararlas en cualquier parte fuera de una función. Pueden ser accedidas por cualquier expresión independientemente de la función en la que se encuentre la expresión. En el programa que sigue se puede ver que la variable cuenta ha sido declarada fuera de todas las funciones. Aunque se declaración aparece antes de la función main(), se podría haber colocado en cualquier lugar anterior a su primer uso, mientras no sea en una función. Sin embargo, lo mejor es declarar todas las variables globales al principio del programa.
  • 22. # include <stdio.h> void func1 ( void), func2(void); int cuenta; /* cuenta es global */ main ( void ) { cuenta = 100 ; func1() ; return 0; /* comunicar el éxito al programa */ } void func1 ( void ) void func2 ( void ) { { int temp; int cuenta; temp = cuenta ; for ( cuenta = 1; cuenta <10; cuenta++) func2() ; putchar(‘_’) ; printf( “cuentas es %d”, cuenta ); } }
  • 23. Observando detenidamente este programa, debe estar claro que aunque ni main() ni func1() han declarado la variable cuenta, ambas pueden usarla. Sin embargo, la func2() declara una variable local llamada cuenta. Cuando func2() hace referencia a cuenta, sólo hace referencia a su variable local, no a la global. Si una variable global y una variable local tienen el mismo nombre, todas las referencias a ese nombre de variable dentro de la función donde se ha declarado la variable local se refieren a esa variable local y no tienen efecto sobre la variable global. Esto es algo conveniente. Sin embargo, si se olvida, el programa puede actuar de forma extraña, incluso aunque “ parezca “ correcto. El almacenamiento de las variables globales se hace en una región de memoria fija establecida para este propósito por el compilador. Las variables globales son muy útiles cuando se usan los mismos datos en varias funciones del programa. Sin embargo, se debe evitar el uso de variables globales innecesarias, por tres razones : 1.- Utilizan memoria todo el tiempo de ejecución del programa, no solo cuando se necesitan. 2.- El uso de una variable global cuando se podría usar una variable local hace que la función sea menos general debido a que depende de algo que debe estar definido fuera de ella. 3.- El uso de un gran número de variables globales puede producir errores en el programa debido a efectos secundarios desconocidos y no deseables.
  • 24. Por ejemplo, a continuación se muestran dos formas de escribir mul () – una sencilla función que calcula el producto de dos enteros . General Espeficica mul ( inte x, int y ) int x, y ; { mul ( void ) return ( x * y ) { } return ( x * Y ) } Ambas funciones devuelven el producto de las variables x e y. Sin embargo, la versión generalizada, o parametrizada, se puede usar para devolver el producto de cualesquiera dos enteros, mientras que la versión específica sólo se puede usar para calcular el producto de las variables globales x e y.
  • 25. Las variables son definidas utilizando un identificador de tipo seguido del nombre de la variable. Veamos el siguiente programa. #include <stdio.h> main() { float cels, farh; farh = 35.0; cels = 5.0 * ( farh - 32.0 ) / 9.0; printf(">>> %f F son %f Cn", farh, cels ); } En el programa anterior se definen dos variables float, se asigna un valor a la primera y se calcula la segunda mediante una expresión aritmética. Las asignaciones en C también son una expresión, por lo que se pueden utilizar como parte de otra expresión, pero según que prácticas de este tipo no son muy recomendables ya que reducen la legibilidad del programa. En la instrucción printf, el símbolo %f indica que se imprime un número en coma flotante.
  • 26. Hay un tipo muy importante que se representa por void que puede significar dos cosas distintas, según su utilización. Puede significar nada, o sea que si una función devuelve un valor de tipo void no devuelve ningún resultado, o puede significar cualquier cosa, como puede ser un puntero a void es un puntero genérico a cualquier tipo de dato. Más adelante veremos su utilización. Funciones Un programa C está formado por un conjunto de funciones que al menos contiene la función main. Una función se declara con el nombre de la función precedido del tipo de valor que retorna y una lista de argumentos encerrados entre paréntesis. El cuerpo de la función está formado por un conjunto de declaraciones y de sentencias comprendidas entre llaves. Veamos un ejemplo de utilización de funciones:
  • 27. #include <stdio.h> int fact_r ( int v ) #define VALOR 5 { #define FACT 120 if ( v == 0 ) int fact_i ( int v ) return 1; { else int r = 1, i = 0; return v * fact_r(v-1); while ( i <= v ) { } r = r * i; i = i + 1; } return r; }
  • 28. main() { int r, valor = VALOR; if ( (r = fact_i(valor)) != fact_r(valor) ) printf("Codificación errónea!!.n"); else if ( r == FACT ) printf("Codificación correcta.n"); else printf("Algo falla!!.n"); }
  • 29. Se definen dos funciones, fact_i y fact_r, además de la función main. Ambas toman como parámetro un valor entero y devuelven otro entero. La primera calcula el factorial de un número de forma iterativa, mientras que la segunda hace lo mismo de forma recursiva. Todas las líneas que comienzan con el símbolo # indican una directiva del precompilador. Antes de realizar la compilación en C se llama a un precompilador cuya misión es procesar el texto y realizar ciertas sustituciones textuales. Hemos visto que la directiva #include incluye el texto contenido en un fichero en el fuente que estamos compilando. De forma parecida, #define nombre texto sustituye todas las apariciones de nombre por texto. Así, en el fuente, la palabra VALOR se sustituye por el número 5. El valor que debe devolver una función se indica con la palabra return. La evaluación de la expresión debe dar una valor del mismo tipo de dato que el que se ha definido como resultado. La declaración de una variable puede incluir una inicialización en la misma declaración. Se debe tener muy en cuenta que en C todos los argumentos son pasados 'por valor'. No existe el concepto de paso de parámetros 'por variable' o 'por referencia'. Veamos un ejemplo:
  • 30. int incr ( int v ) main() { { return v + 1; int a, b; b = 3; } a = incr(b); /* a = 4 mientras que b = 3. No ha cambiado después de la llamada. */ } En el ejemplo anterior el valor del parámetro de la función incr, aunque se modifique dentro de la función, no cambia el valor de la variable b de la función main. Todo el texto comprendido entre los caracteres /* y */ son comentarios al programa y son ignorados por el compilador. En un fuente C los comentarios no se pueden anidar.
  • 31. Expresiones y operadores Los distintos operadores permiten formar expresiones tanto aritméticas como lógicas. Los operadores aritméticos y lógicos son: +, - suma, resta ++, -- incremento, decremento *, /, % multiplicación, división, módulo >>, << rotación de bits a la derecha, izquierda. & AND booleano | OR booleano ^ EXOR booleano ~ complemento a 1 ! complemento a 2, NOT lógico ==, != igualdad, desigualdad &&, || AND, OR lógico <, <= menor, menor o igual >, >= mayor, mayor o igual
  • 32. En estos operadores deben tenerse en cuenta la precedencia de operadores y las reglas de asociatividad, que son las normales en la mayoría de lenguajes. Se debe consultar el manual de referencia para obtener una explicación de tallada. Además hay toda una serie de operadores aritméticos con asignación, como pueden ser += y ^=. En la evaluación de expresiones lógicas, los compiladores normalmente utilizan técnicas de evaluación rápida. Para decidir si una expresión lógica es cierta o falsa muchas veces no es necesario evaluarla completamente. Por ejemplo una expresión formada <exp1> || <exp2>, el compilador evalúa primero <exp1> y si es cierta, no evalúa <exp2>. Por ello se deben evitar construcciones en las que se modifiquen valores de datos en la propia expresión, pues su comportamiento puede depender de la implementación del compilador o de la optimización utilizada en una compilación o en otra. Estos son errores que se pueden cometer fácilmente en C ya que una asignación es también una expresión. Debemos evitar: if (( x++ > 3 ) || ( x < y )) y escribir en su lugar: x++; if (( x > 3 ) || ( x < y ))
  • 33. Hay un tipo especial de expresión en C que se denomina expresión condicional y está representada por los operadores ? : . Su utilización es como sigue: <e> ? <x> : <y>. Se evalúa si e entonces x; si no, y. int mayor ( int a, int b ) { return ( a > b ) ? TRUE : FALSE; } waste_time () { float a, b = 0.0; ( b > 0.0 ) ? sin(M_PI / 8) : cos(M_PI / 4); }
  • 34. Conversión de tipos Cuando escribimos una expresión aritmética a+b, en la cual hay variables o valores de distintos tipos, el compilador realiza determinadas conversiones antes de que evalúe la expresión. Estas conversiones pueden ser para 'aumentar' o 'disminuir' la precisión del tipo al que se convierten los elementos de la expresión. Un ejemplo claro, es la comparación de una variable de tipo int con una variable de tipo double. En este caso, la de tipo int es convertida a double para poder realizar la comparación. Los tipos pequeños son convertidos de la forma siguiente: un tipo char se convierte a int, con el modificador signed si los caracteres son con signo, o unsigned si los caracteres son sin signo. Un unsigned char es convertido a int con los bits más altos puestos a cero. Un signed char es convertido a int con los bits más altos puestos a uno o cero, dependiendo del valor de la variable. Para los tipos de mayor tamaño: si un operando es de tipo double, el otro es convertido a double. Si un operando es de tipo float, el otro es convertido a float. Si un operando es de tipo unsigned long, el otro es convertido a unsigned long. Si un operando es de tipo long, el otro es convertido a long. Si un operando es de tipo unsigned, el otro es convertido a unsigned. Si no, los operandos son te tipo int.
  • 35. Una variable o expresión de un tipo se puede convertir explícitamente a otro tipo, anteponiéndole el tipo entre paréntesis. cambio_tipo () { float a; int b; b = 10; a = 0.5; if ( a <= (float) b ) menor(); }
  • 36. Control de flujo. La sentencia de control básica es if (<e>) then <s> else <t>. En ella se evalúa una expresión condicional y si se cumple, se ejecuta la sentencia s; si no, se ejecuta la sentencia t. La segunda parte de la condición, else <t>, es opcional. int cero ( double a ) { if ( a == 0.0 ) return (TRUE); else return (FALSE); }
  • 37. En el caso que <e> no sea una expresión condicional y sea aritmética, se considera falso si vale 0; y si no, verdadero. Hay casos en los que se deben evaluar múltiples condiciones y únicamente se debe evaluar una de ellas. Se puede programar con un grupo de sentencias if then else anidadas, aunque ello puede ser farragoso y de complicada lectura. Para evitarlo nos puede ayudar la sentencia switch. Su utilización es: switch (valor) { case valor1: <sentencias> case valor2: <sentencias> ... default: <sentencias> }
  • 38. Cuando se encuentra una sentencia case que concuerda con el valor del switch se ejecutan las sentencias que le siguen y todas las demás a partir de ahí, a no ser que se introduzca una sentencia break para salir de la sentencia switch. Por ejemplo, ver_opcion ( char c ) { switch(c) { case 'a': printf("Op An"); break; case 'b': printf("Op Bn"); break; case 'c': case 'd': printf("Op C o Dn"); break; default: printf("Op ?n"); } }
  • 39. Otras sentencias de control de flujo son las que nos permiten realizar iteraciones sobre un conjunto de sentencias. En C tenemos tres formas principales de realizar iteraciones. La sentencia while (<e>) <s> es seguramente la más utilizada. La sentencia, o grupo de sentencias <s> se ejecuta mientras la evaluación de la expresión <e> sea verdadera. long raiz ( long valor ) { long r = 1; while ( r * r <= valor ) r++; return r; }
  • 40. Otra sentencia iterativa, que permite inicializar los controles del bucle se la sentencia for ( <i>; <e>; <p> ) <s>. La sentencia for se puede escribir también como: <i>; while ( <e> ) { <s>; <p>; } El ejemplo anterior se podría escribir como: long raiz ( long valor ) { long r; for ( r = 1; r * r <= valor; r++ ) ; return r; }