Capítulo 3 Lenguaje C

19
Capítulo 3 http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.] Capítulo 3 1. Lenguaje de programación C (Continuación) 1. Funciones Un programa se compone de un conjunto de funciones. Las funciones son equivalentes a una subrutina o procedimiento y pueden aparecer en cualquier orden en el archivo fuente. Para llamarlas se utiliza su nombre y pueden regresar un solo valor. El tipo de la función es el tipo del valor de retorno. La comunicación entre la función que llama y la función llamada se puede realizar por medio de : Variables globales. Paso de parámetros. La forma general es: ( tipo de dato ) nombre_de_función (declaración de parámetros ) { declaración de variables locales proposición 1; proposición 2; . . proposición n; return (expresión); } Antes del estándar ANSI, las funciones se definían ( tipo de dato ) nombre_de_función (parámetros ) declaración de parámetros { declaración de variables locales proposición 1; proposición 2; . .

description

Programacion

Transcript of Capítulo 3 Lenguaje C

Page 1: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

Capítulo 3

1. Lenguaje de programación C(Continuación)

1. Funciones

Un programa se compone de un conjunto de funciones.

Las funciones son equivalentes a una subrutina o procedimiento y pueden aparecer en cualquier orden en el archivo fuente. Para llamarlas seutiliza su nombre y pueden regresar un solo valor.

El tipo de la función es el tipo del valor de retorno.

La comunicación entre la función que llama y la función llamada se puede realizar por medio de :

Variables globales.Paso de parámetros.

La forma general es:

( tipo de dato ) nombre_de_función (declaración de parámetros )

{

declaración de variables locales

proposición 1;

proposición 2;

.

.

proposición n;

return (expresión);

}

Antes del estándar ANSI, las funciones se definían

( tipo de dato ) nombre_de_función (parámetros )

declaración de parámetros

{

declaración de variables locales

proposición 1;

proposición 2;

.

.

Page 2: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

proposición n;

return (expresión);

}

Este estilo todavía es valido, pero esta cayendo en desuso.

Las funciones descomponen tareas computacionales largas en otras más pequeñas, y permiten al programador "construir a partir de lo queotros han hecho en lugar de empezar desde cero". La funciones construidas apropiadamente ocultan los detalles de su operación a otras partesdel programa que no necesitan saber acerca de ellas.

El lenguaje C ha sido diseñado para hacer las funciones eficientes y fáciles de usar; los programas en C generalmente consisten de muchasfunciones pequeñas en vez de pocas grandes. Un programa puede residir en uno o más archivos fuentes. Los archivos fuente pueden sercompilados por separado y cargados en conjunto, junto con funciones previamente compiladas de las librerías.

1. La proposición return.

El return, es el mecanismo para devolver un valor de una función a la función que la llamó.

El return puede ir seguido de una expresión, que es el valor que recibe la función que llama:

return (expresión);

Sí el return no va seguido de una expresión, no se devuelve valor alguno.

La función que llama puede ignorar el valor regresado por return.

Sí no se incluye return en la función, al encontrar la llave de retorno de esta se regresa el control a la función que llamó sin regresar valoralguno.

La expresión que devolverá la proposición return será convertida al tipo de retorno de la función sí es necesario. Los paréntesis generalmenteson usados alrededor de la expresión, aunque son opcionales.

1. Funciones no enteras.

Sí el valor de retorno de una función no es de tipo int, es necesario declarar el tipo de la función en ella y en la función que llama, mediante unprototipo.

Ejemplo:

#include <stdio.h>

#include <ctype.h>

#define MAXLINEA 100 /* tamaño máximo de la línea */

double atof(char [ ]); /* declaración de prototipos de funciones no enteras */

int main(void)

{

double suma;

Page 3: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

int digito; /* digito convertido */

char linea[MAXLINEA]; /* línea de entrada */

suma = 0;

printf ( "Dame la cadena de caracteres a convertir: ");

while ( getline (linea, MAXLINEA) > 0 ) {

printf ( "\n La cadena leída fué: %s ", linea);

printf ( "\n\t suma = %.2f \n\n", suma += atof(linea));

printf ( "Dame la cadena de caracteres a convertir:");

}

return (0);

}

/* Nota: la función getline( ) lee de stdin una línea de texto y la guarda en el arreglo linea[ ] */

/* atof convierte cadena a número de doble precisión */

double atof (char cadena[ ])

{

double valor, potencia;

int i, signo;

for ( i=0; isspace(cadena[i]); i++) /* salta blancos */

; /* proposición nula */

signo = (cadena[i] == '-') ? -1 : 1;

if ((cadena[i] == '+') | | (cadena[i] == '-'))

i++;

for ( valor = 0.0; isdigit(cadena[i]); i++);

valor = 10.0 * valor + (cadena [i] - '0');

if (cadena[i] == '.') i++; /* parte fraccionaria */

for (potencia = 1.0; isdigit(cadena[i]); i++) {

valor = 10.0 * valor + (cadena[i] - '0' );

potencia *= 10.0;

}

return (signo * valor / potencia); /* valor de regreso */

}

/* Nota: la función isspace( ) checa sí el carácter es espacio, tabulador o nueva línea */

/* Nota: la función isdigit( ) checa sí el carácter es un dígito */

Page 4: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

Puesto que las funciones devuelven un valor de tipo int por omisión, sí se desea que la función devuelva un valor de otro tipo es necesarioexpresarlo explícitamente mediante un prototipo.

Así por ejemplo:

suma (int x, int y)

{

.

.

.

}

es equivalente a:

int suma (int x, int y)

{

.

.

.

}

Sí una función no va a regresar algún valor esta debe de declararse de tipo void. Sí además no requiere argumentos entonces se emplea voidcomo declaración de parámetros. Todo esto fue introducido con el estándar ANSI.

void Nombre_funcion(void); /* Prototipo de una función que regresa algún valor y no requiere parámetros */

En el caso de funciones de tipo void el return es opcional, pero sí se incluye en este no se debe de indicar algún valor de retorno. Losprototipos usualmente se colocan después de los headers, antes del main.

1. Paso de parámetros.

El paso de parámetros a una función siempre se hace por valor.

La función recibe una copia de los parámetros.

En una función, cada parámetro es una variable local inicializada con el valor del parámetro que se llamó a la función.

Se puede pensar que los arreglos se pasan por referencia, ya que los cambios que se hagan sobre los mismos sí afectan a la variable original.

En general, el paso de parámetros por referencia, dentro del lenguaje C, se realiza mediante el paso por valor de las direcciones de memoriadonde se encuentran almacenadas las variables que se desean referenciar.

1. Alcance de validez.

Una variable global se debe declarar con extern cuando se quiera accesar: en otro archivo diferente a donde se definió, antes de definirla en elmismo archivo.

Ejemplo:

Archivo dec.c:

Page 5: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

float val[MAXVAL]; /* variable global (pila) */

int sp = 0; /* variable global (posición) */

Archivo stack.c:

#include <stdio.h>

#define MAXVAL 100 /* tamaño máximo de la pila val */

int push(float); /* prototipo de la función */

extern int sp; /* declaración de sp */

extern float val[ ]; /* declaración de val */

/* función push( ): inserta el siguiente valor en la pila */

int push(float f)

{

if(sp<MAXVAL) /* sí hay lugar en la pila */

val[sp++] = f;

else

printf("pila llena, no se puede insertar %f\n",f);

}

Las funciones y variables que componen un programa en C no requieren ser compilados al mismo tiempo; el código fuente de un programapuede ser guardado en varios archivos, y las rutinas previamente compiladas pueden ser cargadas de las librerías.

El alcance de validez de una variable es la parte del programa dentro de la cual la variable puede ser usada. Para una variable declarada alprincipio de una función (variable local), el alcance de validez es la función dentro de la cuál la variable fué declarada.. Las variables localescon el mismo orden en funciones diferentes no guardan relación. Lo mismo se aplica a los parámetros de una función, que son en efectovariables locales.

El alcance o validez de variables externas o de una función perdura en el punto en el cuál son declaradas hasta el final del archivo que secompila.

1. Almacenamiento

Como comentamos en el capítulo anterior, un atributo de los operandos, concretamente para las variables es el almacenamiento. Este se refierea como se almacena en memoria las variables. Los tipos de almacenamiento son:

Variables automáticas

Page 6: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

Variables estáticasVariables registroVariables externas

1. Variables Automáticas

Al menos que se indique lo contrario, el tipo de almacenamiento de todas las variables en C son como variables automáticas, esto es soloexisten mientras se ejecuta el código donde están declaradas. Esto hace mas eficiente el manejo de la memoria, puesto que las variables soloocupan espacio, cuando se requieren, dejando de existir al terminar el código donde se ocupan. Estas variables se inicializan en tiempo deejecución, puesto que se crean y destruyen continuamente. Sí se desea se puede declara explícitamente una variable como automática usando lapalabra reservada auto:

auto int conta;

auto float sum;

1. Variables Estáticas

Se definen como static.No se destruyen ni pierden su valor al terminar la función que las define.Solo se inicializan la primera vez que se llama a la función.Sí se definen como globales, solo se pueden accesar en el archivo donde se definieron.

Ejemplo:

int cuenta (void) /* regresa el número de llamadas a la función */

{

static cuenta = 0;

return cuenta++;

}

Las variables locales definidas y sus respectivos archivos fuente, no se supone que sean acezadas nada más. La declaración static aplicada auna variable externa o función, expande al alcance de dicho objeto al resto del archivo fuente siendo compilado.

La declaración extern static es generalmente empleada en variables, pero puede ser empleada a sí mismo a funciones. Normalmente, el nombrede funciones son globales visibles a cualquier parte del programa. Sí una función es declarada static, su nombre es invisible fuera del archivoen el cual fue declarada.

La declaración static puede ser también aplicada a variables internas. Variables internas static son locales a una función particular de la mismaforma que lo son las variables locales (automáticas), pero a diferencia de éstas, aquellas permanecen en existencia en lugar de reservarse yliberarse espacio en memoria para ellas cada vez que es llamada la función. Eso significa que las variables internas static proveenalmacenamiento privado y permanente dentro de una función.

1. Variables registro.

Se declaran como register.Se utilizan para variables usadas intensamente.Le dan velocidad a la ejecución del programa y disminuyen su tamaño.Son variables que el compilador trata de almacenar en los registros internos del CPU.Solo pueden emplearse en variables de tipo int, char ó sus derivados con los modificadores de tipo.

Ejemplo:

register int i, tmp;

for ( i=0; i<MAX; i++) {

tmp = arr1[i];

Page 7: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

arr1[i] = arr2[i];

arr2[i] = tmp;

}

Una declaración register le advierte al compilador que la variable en cuestión será altamente usada. La idea es que variables register han de sercolocadas en los registros del microprocesador, lo que puede resultar en programas más pequeños y rápidos. El compilador tiene la libertad deignorar esta declaración. Razón por la cual se dice que esta declaración es una sugerencia al compilador.

La declaración register sólo puede ser aplicada a variables locales y a los parámetros formales de un función. Para este último caso, se hace:

if (register unsigned m, register long n)

{

register int i;

.....

}

En la práctica existen restricciones para las variables register, reflejando las realidades del hardware subyacente. Únicamente una cuantasvariables en cada función pueden ser almacenadas en registros, y solo ciertos tipos son permitidos. Las declaraciones excesivas de variables detipo registro son dañinas, sin embargo, de ésta forma la palabra register es ignorada por exceso. No es posible obtener la dirección de unavariable de este tipo, sin importar de que sí la variable fue realmente colocada en el registro. Las restricciones específicas en el número y tipode variables tipo registro varían de máquina a máquina.

1. Variables Externas o Globales

Son accesibles por todas las funciones del programa.Se definen fuera de cualquier función.

Ejemplo:

#include <stdio.h>

#define MAXVAL 100

void push(float);

float val[MAXVAL]; /* variable global (pila) */

int sp = 0; /* variable global (posición en la pila) */

/* función push( ): insertar el siguiente valor en la pila */

void push(float f)

{

if(sp<MAXVAL) /* sí hay lugar en la pila */

val[sp++] = f;

else

printf("pila llena, no se puede insertar %f\n",f);

}

Las variables globales, para que sean tales (accesibles a todas las funciones de un programa), deben estar definidas antes que el código decualquier función.

Page 8: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

Por otra parte, sí una variable externa ha de ser referenciada antes de que sea definida, o sí es definida en un archivo diferente de donde esusada, entonces una declaración extern es obligatoria.

Es importante distinguir entre la declaración de una variable externa y su definición. Una declaración anuncia las propiedades de una variable(principalmente su tipo ); una definición además causa que se reserve el espacio necesario para almacenar el contenido de la variable.

Por ejemplo, sí las líneas :

int sp;

double val [MAXVAL];

aparecen fuera dentro de cualquier función , éstas definen las variables sp y val , causa que se reserve el espacio para almacenamiento, yademás sirve como declaración para el resto de ese archivo fuente. Por otro lado, las líneas

extern int sp;

extern double vall [ ];

declaran para el resto del archivo fuente, que sp es un entero y que vall es un arreglo ( cuyo tamaño es determinado en algún otro lugar), perono crean las variables o reservan espacio para ellas.

Debe haber solo una definición de una variable externa entre todos los archivos que componen un programa fuente; otros archivos puedencontener declaraciones extern para poder accesarlas. ( Puede haber declaraciones extern en el archivo que contenga la definición). El tamañode los arreglos debe especificarse en la definición, pero son opcionales en la declaración extern.

La inicialización de una variable externa sólo se realiza en la definición.

1. Inicialización

Variables externas y estáticas:Se inicializan con ceroSe inicializan una sola vez, en tiempo de compilaciónSolo se pueden utilizar expresiones constantes.Los arreglos externos y estáticos pueden ser inicializados.Se reserva espacio al momento de la compilaciónVariables locales ( automáticas) y registro:No se inicializan a cero: contienen " basura"Se crean cada vez que se entra a la rutina o bloque y, se destruyen cuando se sale de esta.Se inicializan en cada entrada a la rutina o bloque, sí su inicialización es explícita.Pueden inicializarse con cualquier expresión, incluso llamadas a funciones.Se reserva espacio al momento de la ejecución

1. Recursividad

Son funciones que se llaman a ellas mismas.El llamado a ellas mismas debe estar condicionado.Se debe asegurar que esta condición debe dejar de cumplirse en algún momento.

Ejemplo:

itoa(int numero, char cadena[ ])

{

static int i;

if ( numero / 10)

itoa ( numero / 10 , cadena);

else{

Page 9: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

i = 0;

if (numero < 0 ) { /* Sí el numero era negativo * /

numero = - numero;

/* Convierte num en positivo * /

cadena [i++] = '-';

}

}

cadena [i++] = numero % 10 + '0';

cadena [ i ] = ' \ 0' ;

}

Las funciones de C pueden ser usadas recursivamente; esto es, una función puede llamarse a ella misma tanto directa como indirectamente.Cuando una función se llama a ella misma recursivamente, cada invocación obtiene una copia de las variables locales, independientemente delconjunto previo. La recursión puede no proporcionar ahorro en el almacenamiento, puesto que en algún lugar debe existir un stack (pila) de losvalores que están siendo procesados. Tampoco será más rápido, pero el código recursivo es más compacto y, muchas veces más fácil deescribir y entender que el equivalente no recursivo .

1. El procesador: inclusión de archivos

El archivo incluido se inserta literalmente en el archivo actual.

Solo inserta archivos de texto ASCII, que contienen código C.

Sintaxis:

# include < nombre- archivo>

# include " nombre - archivo"

En UNIX busca el < nombre - archivo> en el directorio / usr / include

# include < stdio.h >

# include < ctype.h>

# include < sys/ inode.h>

Busca normalmente " nombre - archivo" en el directorio de trabajo

# include " calc.h"

Esta directiva al preprocesador del compilador, el cuál, conceptualmente, es un primer paso independiente en el proceso de compilación .

Esta directiva como su nombre indica, es reemplazada por el contenido del archivo indicado en esta directiva, que dependiendo de la sintaxisse indica de qué lugar debe obtenerse el archivo.

1. El preprocesador: Macros

Se usan para abreviar textos, evitar el uso excesivo de funciones y para modificar fácilmente un programaSubstituyen el texto definido en donde aparezca la macro antes de compilar.

Ejemplo 1:

# define MAX 100

Page 10: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

for ( i = 0 ; i < MAX; i++) -> for ( i = 0 ; i < 100 ; i++)

Ejemplo 2:

# define square( x) X * X /* Incorrecto * /

# define square (x) (x) * (x) / * Correcto * /

# define max ( A, B) ((A) > (B) ? (A) : (B))

x = max ( i++, j++ ); / * No funciona */

x = max ( p+q, r+s); --> x = (( p+q) > ( r+s) ? ( p+q) : ( r+s));

1. Apuntadores

Los apuntadores forman parte de las características avanzadas del lenguaje C y son ampliamente utilizados por un buen programador. Losapuntadores permiten accesar grandes cantidades de información sin tener que moverla o copiarla, lo que acelera inmensamente la velocidadde ejecución.

Toda variable se almacena en memoria, y la memoria se accesa a través de direcciones. UNA VARIABLE QUE ALMACENA UNADIRECCIÓN DE MEMORIA ES UN APUNTADOR. En sí un apuntador es otro tipo de variable, pero en vez de guardar enteros o caracteresguarda direcciones de memoria. El tamaño de los apuntadores varía de acuerdo con la computadora, pero lo común es que sea de 4 bytes.

Sí por ejemplo, en la dirección almacenada en el apuntador "p" se guarda la variable "suma" decimos que "p apunta a suma". Nótese que "p"es otra variable, por lo que se almacena en otra dirección.

Memoria de la Computadora.

Dirección Nombre de la variable

Decimos que "p" apunta a suma.

Finalmente, hay diferentes tipos de apuntadores dependiendo del tipo de variable que se guarde en la dirección que almacenan. Así porejemplo, sí en el caso anterior "suma" fuera del tipo int, entonces "p" es un apuntador a enteros; sí "suma" fuera del tipo char, entonces "p" esun apuntador a caracteres, etc. Todos estos apuntadores tienen el mismo tamaño, pero no son del mismo tipo.

Con los apuntadores, podemos modificar su valor (hacer que apunten a otro lado) o bien modificar a lo que apuntan.

1. Declaración y operadores.

Como cualquier variable, los apuntadores se tienen que definir antes de utilizarlos .La sintaxis para esto es:

Donde:

Page 11: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

"tipo" es cualquier tipo de variable y

"apuntador" es el nombre del apuntador.

Declaración:

int sal = 8; /* entero */

int *ap; /* apuntador a entero */

ap /* es de tipo apuntador a int */

*ap /* es de tipo int (contenido) */

char *apcar /* apuntador a carácter

apcar /* es de tipo apuntador a char */

* apcar /* es de tipo char (contenido) */

En este ejemplo, "ap" es un apuntador a entero, mientras "sal" guarda enteros, "ap" guarda direcciones donde se almacenan enteros, etc.

Sí queremos declarar un apuntador a apuntador a char (un apuntador que guarda la dirección donde se almacena otro apuntador y éste guarda ladirección donde se almacena un char), tendríamos que declarar:

char ** var; /* apuntador a apuntador a carácter */

char *var[]; /* apuntador a apuntador a carácter */

char var[][]; /* apuntador a apuntador a carácter */

1. Operadores:

Para usar utilizar los apuntadores eficientemente, veremos dos operadores:

Este operador se utiliza con variables regulares para obtener la dirección i donde se almacenan ( Proporciona la dirección de una variable).

&sal - > significa la dirección donde se guarda la variable "sal"

Se utiliza solo con apuntadores, y significa el contenido de lo que apunta; o más correctamente, el contenido de la dirección almacenada en elapuntador (Proporciona el contenido de la dirección almacenada en la variable).

*sal -> significa el contenido de la dirección almacenada en "sal".

Es MUY IMPORTANTE inicializar los apuntadores antes de utilizarlos, ya que inicialmente apuntan a una dirección desconocida. El uso deun apuntador no inicializado no genera errores en la compilación, pero en la ejecución puede generar el error "memory fault: core dumped".Un valor con el que se puede inicializar un apuntador es el cero de los apuntadores, denominado dirección nula. Se representa con la macroNULL. Es importante no intentar recuperar lo que esta almacenado en NULL, puesto que también puede producir fallas en el sistema.

Así tenemos:

sal = 8;

Page 12: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

ap = &sal;

inicializamos a "ap" haciendo que apunte a "sal".

Sí posteriormente tenemos que:

*ap = 9; /* contenido */

estamos modificando a la variable "sal", es como haber tenido:

sal = 9

*ap : " es el valor de la variable apuntada por ap ".

& sal = 1024

* ap = 8

sal = 8

Suponiendo que p y q son apuntadores a int y que tienen el siguiente estado inicial:

a = 7

b = 2

La figura anterior muestra dos ejemplos de asignación usando apuntadores:

En el primero ( p = q ), estamos igualando el contenido de "p" al de "q"; como este valor es una dirección, hacemos que ambosapuntadores apunten a un mismo lugar . La dirección original almacenada en "p" se pierde.En el segundo ( *p = *q ), estamos igualando el contenido de lo que apunta "p" al contenido de lo que apunta "q". Los apuntadores nose modifican, solo los contenidos de lo que apuntan. En este caso el contenido inicial de lo que apuntaba "p" se pierde.

El código para obtener el estado inicial podría ser:

int a, b, *p, *q;

Page 13: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

a = 7;

b = 2;

p = &a;

q = &b;

Nótese que al definir un apuntador a entero, no se reserva memoria para un entero sino para una dirección por lo que todos los apuntadores sinimportar el tipo de variable al que apunten son de 4 bytes.

EJERCICIO:

De que tipo son:

int x;

int *ap;

int **ap1;

x : ________________ R: entero

ap : ________________ R: apuntador a entero

*ap: ________________ R: entero

ap1: ________________ R: apuntador a apuntador a entero

*ap1: _______________ R: apuntador a entero

**ap1: ______________ R: entero

1. Aritmética de apuntadores.

Observa el siguiente ejemplo:

int a[10], *ap,*bp;

ap = a; /* dirección del primer elemento */

ap = & a[0] /* Esto equivale a la linea anterior */

( ap + 1 ) equivale a & a[1]

( ap + 8 ) equivale a & a[8]

( ap + 5 ) equivale a & a[0] + ( 2 * sizeof(int) )

ap ++ /* apunta a & a[1] */

ap += 3 /* apunta a & a[4] */

bp = &a[9]; /* ultimo elemento */

ap = a; /* dirección del primer elemento */

El nombre de un arreglo es un apuntador al primer elemento del mismo, por eso basta con asignársele el nombre a un apuntador, para que este

Page 14: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

apunte al inicio del arreglo.

Cuando le sumamos un entero a un apuntador, este avanza tantas direcciones como bytes ocupe el tipo de dato del arreglo. En el ejemplo dearriba nota que los apuntadores se incrementan de 4 en 4

La resta de apuntadores es valida siempre y cuando ambos apunten a un mismo arreglo, el resultado es el numero de celda que existen entre lasceldas apuntadas. Si restamos bp-ap obtenemos 9

Los apuntadores pueden compararse entre si, siempre y cuando apunten a un mismo arreglo. Las comparaciones se hacen en base a la posicionde las celdas apuntadas. Por ejemplo:

if (ap == bp) /* es falsa */

if (ap != bp ) /* es cierta */

if (ap > bp ) /* es falsa */

if (ap < bp ) /* es cierta */

if (ap >= bp ) /* es falsa */

if (ap <= bp ) /* es cierta */

Cualquier otra operación con apuntadores NO ES VALIDA.

1. Apuntadores y elementos de un arreglo.

Cuando definimos un arreglo, el nombre del arreglo es un apuntador constante al inicio de éste (al primer elemento) y lo podemos utilizar ennuestro programa como cualquier otra constante. Una aplicación bastante útil es mandar esa constante a una función para pasarle el arreglo, envez de pasarle elemento por elemento.

Por ejemplo:

int ent[20];

char nombre[50];

Donde:

"int" : es un apuntador a entero

"nombre" : es un apuntador a char

*ent = 45; /* ent[0] = 45 */

*nombre = "j" /* nombre[0] = "j" */

En general:

Ejemplo:

char arr[20];

arr = &arr[0] -> arr se define como &arr[0] y es un apuntador

constante.

arr[0] = *(arr + 0) -> arr[0] se define como *(arr + 0) o simplemente

*arr

Page 15: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

arr[8] = *(arr + 8) -> arr[8] se define como *(arr + 8)

Y en general:

arr[i] = *(arr + i) -> arr[i] se define como *(arr + i)

Ejemplo:

strlen (char *apcad)/* regresa el número de caracteres de un arreglo */

/* apcad apunta al primer carácter del arreglo */

{

int n;

for ( n=0; *apcad != '\0'; apcad++ )

n++;

return (n);

}

/* Otra opción del for: for ( n=0; apcad[n] != '\0'; n++ ); */

1. Paso de parámetros por referencia.

En C el paso de parámetros a las funciones siempre se hace por valor ( se crea una variable local y se inicializa con el valor de la variableoriginal ), pero usando apuntadores se puede simular el paso de parámetros por referencia ( los cambios de la variable local se reflejan en lavariable original ). En vez de mandar a la variable, se manda la dirección de la variable, por lo que la función recibe un apuntador.

Las variables originales se pueden modificar cambiando los contenidos de los apuntadores.

En el siguiente ejemplo la función intercambia ( ) recibe a "px" apuntando a "uno" y a "py" apuntando a "dos", y los cambios a *px y *py sereflejan en "uno y "dos".

# include <stdio.h>

int main(void )

{

int uno, dos;

uno = 1;

dos = 2;

printf ( "Los valores iniciales son: %d (uno) y %d (dos) \n", uno, dos);

intercambia(&uno,&dos);

printf ( "y después de intercambia( ) son: %d (uno) y %d (dos) \n", uno, dos);

return (0);

}

int intercambia (int *px, *py)

{

Page 16: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

int temp;

temp = *px;

*px = *py;

*py = temp;

}

Solo se puede simular pasando a la función las direcciones de las variables originales.

1. Paso de Arreglos a funciones.

Como mencionamos anteriormente, el nombre de un arreglo es un apuntador constante al primer elemento del arreglo. Es muy fácil mandargran cantidad de información en un arreglo a una función, mandando solamente el apuntador al arreglo, además de ganar velocidad en laejecución.

En el siguiente ejemplo, se muestran tres versiones de la función:

Copia un arreglo de caracteres a otro.

De hecho, en las tres versiones strcpy ( ) recibe dos apuntadores a caracteres: uno del arreglo a copiar y otro del arreglo donde se guardará lacopia. La declaración:

y se puede usar indistintamente el apuntador con corchetes o con asterisco.

Antes de llamar a strcpy( ), se tuvo que hacer una definición como:

char orig[20] = "Cadena original"; /* variable global */

char dest[20];

y luego llamar a la función:

strcpy(dest, orig);

Siempre que se manejan arreglos de caracteres, al final de las cadenas debe existir el carácter nulo ('\0').

Ejemplo:

void strcpy (char s[ ], t[ ]) /* copia t a s usando arreglos */

{

int i;

i = 0;

while (( s[i] = t[i] ) != '\0' )

Page 17: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

i++;

}

void strcpy (char *s, char *t ) /* versión con apuntadores */

{

while (( *s = *t ) != '\0' ) {

s++;

t++;

}

}

void strcpy (char *s, char *t )/* versión compacta con apuntadores */

{

while ( *s++ = *t++ )

;

}

La ventaja de usar apuntadores sobre la de usar arreglos es que el código de máquina es más rápido, compacto y eficiente a traducirlo ainstrucciones en lenguaje de máquina. De tal forma que el código de apuntadores se ejecuta a mayor velocidad.

1. Estructuras.

En el lenguaje C, una estructura es una colección de variables que se denomina bajo un único nombre, proporcionando un medio eficaz demantener junta cierta información relacionada. Una declaración de estructura forma una plantilla que puede utilizarse para crear variables deestructura. Las variables que componen la estructura se llaman elementos de la estructura. En general cada elemento de la estructura estarelacionado lógicamente con los otros. Para comprender mejor las estructuras, lo mejor es comenzar con un ejemplo. El código que siguemuestra cómo crear una plantilla de estructura que define los campos de nombre y dirección. La palabra struct indica al compilador que seesta declarando una estructura.

Sintaxis:

struct nombre

{

tipo miembro;

tipo miembro;

. . .

};

Ejemplo:

struct dir {

char nombre[30];

char calle[30];

char ciudad[20];

Page 18: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

char estado[5];

int código;

};

La declaración termina con punto y coma, ya que una declaración de estructura es una sentencia. El nombre de la estructura dir identifica aesta particular estructura de datos y es su especificador de tipo.

En este punto del código, realmente no se han declarado variables. Sólo se ha definido la forma de los datos. para declarar una variable conesta estructura, se escribe:

struct dir informe_dir;

Esto declara una variable de estructura de tipo dir llamada informe_dir. Cuando se declara una estructura, se está definiendo esencialmente untipo complejo de variable compuesto por los elementos de la estructura. No existe realmente una variable de este tipo hasta que se declara.Una forma de simplificar esto es empleando typedef:

typedef struct Dir {

char nombre[30];

char calle[30];

char ciudad[20];

char estado[5];

int código;

} dir;

Con esto podemos declarar ahora:

dir informe_dir;

A los elementos individuales de la estructura se hace referencia utilizando el operador . (denominado operador <<punto>>). Por ejemplo, elsiguiente código asigna el código postal 7260 al campo código de la variable estructura informe_dir declarada anteriormente:

informe_dir.codigo= 7260;

El nombre de la variable de estructura seguido de un punto y del nombre del elemento hace referencia a ese elemento individual de laestructura. A todos los elementos de la estructura se accede de la misma forma. La forma general de acceso es:

nombre_de_estructura.nombre_de_elemento

Así, para imprimir el código postal en la pantalla, escribimos:

printf("%d", informe_dir.codigo);

Esto imprime el código postal que contiene la variable código de la variable estructura informe_dir.

De la misma forma, se puede usar el arreglo de caracteres informe_dir.nombre en una llamada a gets(), como se muestra a continuación.

gets(informe_dir.nombre);

Una estructura se puede copiar en otra asignándola directamente:

copia._dir = informe_dir;

1. Arreglos de estructuras.

Quizá el uso más común de las estructuras es en los arreglos de estructuras. Para declarar un arreglo de estructuras, se debe definir primero laestructura y luego declarar una variable arreglo de dicho tipo. Para declarar un arreglo de estructuras de 50 elementos del tipo dir que se

Page 19: Capítulo 3 Lenguaje C

Capítulo 3

http://sai.uam.mx/apoyodidactico/pa/Unidad3/pauni3.html[03/03/2010 11:53:49 a.m.]

definió anteriormente, se escribiría:

struct dir informe_dir[50];

Esto crea 50 conjuntos de variables organizadas como se haya definido en la estructura dir.

Para acceder a una determinada estructura, se indexa el nombre de la estructura. Por ejemplo, para imprimir el código postal de la cuartaestructura, se escribe:

Como todas las variables arreglo, los arreglos de estructuras comienzan con el índice 0.

1. Índice

3. Lenguaje de programación C (Continuación) 3-13.1. FUNCIONES 3-13.1.1. La proposición return. 3-23.1.2.Funciones no enteras. 3-33.1.3. Paso de parámetros. 3-53.1.4. Alcance de validez. 3-53.1.5. Almacenamiento 3-73.1.5.1. Variables Automáticas 3-73.1.5.2. Variables Estáticas 3-73.1.5.3. Variables registro. 3-83.1.5.4. VariablesExternas o Globales 3-93.1.6. Inicialización 3-113.2. Recursividad 3-113.3. El procesador: inclusión de archivos 3-123.3.1. El preprocesador: Macros 3-133.4. Apuntadores 3-143.4.1. Declaración y operadores. 3-153.4.2.Operadores: 3-163.4.3. Aritmética de apuntadores. 3-193.4.4. Apuntadores y elementos de un arreglo. 3-203.4.5.Paso de parámetros por referencia. 3-223.4.6. Paso de Arreglos a funciones. 3-233.5. Estructuras. 3-253.5.1.Arreglos de estructuras. 3-273.6. Autoevaluacion 3 3-283.7. Índice 3-30