Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Manejo y Tipos de Datos CCS

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 9

Laboratorio de Digitales IV

Manejo de memoria y tipos de datos en Lenguaje C


Informe
Harold Mauricio Dı́az Sebastian Gil González Sebastian Moreno Valencia
Ingenierı́a Electrónica Ingenierı́a Electrónica Ingenierı́a Electrónica
Universidad Tecnológica de Pereira Universidad Tecnológica de Pereira Universidad Tecnológica de Pereira
Pereira, Risaralda Pereira, Risaralda Pereira, Risaralda
Email:harold369@utp.edu.co Email:s.gil@utp.edu.co Email:ss-morevale@utp.edu.co

Resumen—Este documento pretende llevar a cabo el solución al problema planteado, dicho diagrama de flujo puede
análisis del trabajo realizado en la práctica de laboratorio ser visualizado en la figura 1.
correspondiente, en la cual se estudió el manejo de memoria y
tipos de datos en Lenguaje C. Ademas de afianzar y perfeccionar
conceptos previos.

Palabras Clave: Code Composer Studio, Lenguaje C, memoria,


tipos de datos.

I. INTRODUCCI ÓN
C es un lenguaje de programación de próposito general
que ofrece como ventajas economı́a de expresión, control
de flujo y estructuras de datos modernos y un rico conjunto
de operadores. Además, C no es un lenguaje de ”muy alto
nivel”ni ”grande”, y no esta especializado en alguna área
especial de aplicación. Pero su ausencia de restricciones y su
generalidad lo hacen mas conveniente y efectivo para muchas
tareas que otros lenguajes supuestamente mas poderosos.

En este documento se realizará el diseño de varios


algoritmos desarrollados por el software Code Composer
Studio, donde la finalidad es observar todo lo relaciona con
el tipo de datos que tiene lenguaje C, la importancia en
Figura 1. Diagrama de flujo del algoritmo a desarrollar
cuanto a memoria del uso correcto de los diferentes tipos
de funciones, el uso de la memoria dinámica a través de
punteros y comando especiales y el uso de cabeceras para
reducir código principal. Como se observa en el diagrama, primero se definen las 7
variables locales correspondientes a los 7 diferentes tipos de
objetivo Comprender la importancia del uso y la optimiza- datos que tiene lenguaje C. Posteriormente en esas variables
ción de la memoria en los sistemas embebidos. se almacenan los tamaños de cada tipo de dato respectivo.

II. PROCEDIMIENTO
Se procede a realizar el algoritmo en el software Code
II-A. Desarrolle un programa en el cual se observe el Composer Studio utilizando el comando sizeof y luego se
tamaño en bits de los diferentes tipos de datos que tiene hace uso del debug donde en la ventana que se encuentra
lenguaje C (Utilizar el comando sizeof). ubicado el algoritmo, se pone un breakpoint en el final de
Para desarrollar un algoritmo que permita observar el ta- linea y se corre el debug. Se observan entonces los resultados
maño en bits de los diferentes tipos de datos que tiene lenguaje en la ventana watch; dichos resultados pueden ser visualizados
C, primero se realiza el diagrama de flujo que representa la en la figura 2
Ademas, se puede ver que la implementación de la función,
es decir, lo que realiza dicha función multiplicación debe
estar después del código principal. Una vez entendido todo
el diagrama de flujo, se procede a desarrollar el código en el
software Code Composer Studio, donde se realiza de igual
forma la parte del debug como en el primer de código del
presente informe. La ventana watch donde se observan los
resultados se visualiza en la figura 4

Figura 2. Resultados de la simulación del algoritmo desarrollado

Como puede observarse de la figura previa, las variables


definidas tiene almacenado el tamaño de los diferentes tipos
de datos, es importante notar que estos datos están dados en
bytes, por lo que un dato tipo carácter es ”.”, que en código
ASCII es 1 byte. Figura 4. Resultados de la simulación del algoritmo desarrollado

II-B. Realice una función que multiplique dos números uti-


lizando el paso por valor. Donde se puede observar que se esta realizando la multipli-
Se sabe de conocimientos previos, que la función paso por cación de forma correcta :
valor es aquella donde se pasan los datos de entrada por a=5
valor y tiene un retorno. Una vez teniendo esto en cuenta, b=3
se realiza el diagrama de flujo que representa la operación de c = a*b = 5*3 = 15.
multiplicación entre dos números como se observa en la figura
3.
II-C. Realice una función la cual reciba un número y realice
la factorial del dato ingresado (realizar por paso por re-
ferencia y paso por valor) para esto utilice el concepto de
recursividad.

Primero, antes de realizar cualquier diagrama de flujo


correspondiente a la función que exige el ejercicio, es
importante tener claro qué es el concepto de recursividad; en
palabras sencillas se define recursividad como una función
que se llama ası́ misma.

Al tratarse de realizar el factorial de cualquier dato


ingresado es bastante notable aplicar el concepto de
recursividad, por ejemplo :

El factorial de 5:

5! = 5*f4 = 5*4*f3 = 5*4*3*f2 = 5*4*3*2*f1 =


5*4*3*2*1*f0 = 5*4*3*2*1*1 = 120

Donde fn = la función factorial.


Figura 3. Diagrama de flujo del algoritmo a desarrollar
• Factorial utilizando paso por valor:
Como se puede observar en el diagrama correspondiente,
primero se declara la función que en este caso se toma de Una vez comprendido el concepto de recursividad, se pro-
tipo entera, sin embargo se podrı́a tomar de cualquier otro cede a realizar el diagrama de flujo correspondiente a una
tipo de acuerdo a los números que se desean multiplicar. función de tipo paso por valor que retorne el factorial de
Luego, se definen los operandos(a y b) para hacer el llamado cualquier número, en el cual se representa de manera gráfica
de la función con la variable c(producto). la solución al problema planteado; dicho diagrama puede ser
visualizado en la figura 5.
la primera caracterı́stica es que la función es de tipo void, es
decir, que no retorna ningún valor y a su vez en el main se
hace el llamado refiriendo las variables : n(número al cual se
le desea hallar el factorial) y fR(tipo long, donde se desea
almacenar el resultado) y que se inicializa en fR=1, pues el
valor minimo que puede tener es 1(0! o 1!).

Figura 5. Diagrama de flujo del algoritmo a desarrollar

Como se observa en dicho diagrama, se declara una función


que retorna un valor tipo ”long”(f) al ingresarle el número
que se desea calcular el factorial(n), pero como se observa
dentro de la función(implementación) existe un condicional
donde si n mayor a 1 realiza la recursividad, es decir, retorna
el valor ingresado(n) multiplicado por la función factorial
de n-1; donde se puede ver que se llama ası́ mismo dentro Figura 7. Diagrama de flujo del algoritmo a desarrollar
de la misma función, hasta que no cumpla dicha condición.
Cuando ya no cumpla el condicional entonces es conocido
que 1! = 0! = 1. Por otro lado, si se observa la parte del diagrama
correspondiente a la implementación de dicha función tiene
Ya comprendido el diagrama de flujo, se realiza el código la misma regla que la de paso por valor; sin embargo,
en el software Code Composer Studio, y a través del debug al tratarse de paso por referencia es necesario hacer uso
se puede observar los resultados en la ventana watch que se de variables auxiliares, en este caso : int m y long f0, y
observa en la figura 6 teniendo en cuenta el condicional n mayor a 1 se realiza
m=n-1, f0 = *f*n y realiza el llamado de la función de nuevo
(fact(m,&f0)) pero ahora con las variables m y f0 definidas
dentro de la función, una vez que no cumpla con la condición
simplemente multiplica por 1.

Tal vez, no es muy comprensible el entendimiento de


manera grafica ni explicativa, por lo que para un mejor
Figura 6. Resultados de la simulación del algoritmo desarrollado entendimiento se toma n = 6 y en la tabla de la figura 8 se
visualiza como serı́a el proceso de la recursividad cada vez
Como se observa en la figura previa, cuando se tiene un
que se llama la función por referencia definida en el diagrama
número n = 6, se tiene:
de flujo.
6!= 6*5*4*3*2*1 = 720

Que coincide con el valor que tiene la variable f.

• Factorial utilizando paso por referencia:

La diferencia entre una función de paso por valor y


paso por referencia, en términos de notación es que esta
última no rentorna(tipo void), pasa los valores por su
dirección(referencia), es decir, usando & en el momento
que se requiera hacer el llamado de la función en el
código principal,. Sin embargo, para realizar el factorial Figura 8. Proceso de recursividad con la función paso por referencia
de un número utilizando paso por referencia, a pesar de
que se tenga el mismo concepto se debe analizar un poco más.
Posteriormente, se implementa el código en Code Compo-
El diagrama de flujo correspondiente al factorial utilizando ser Studio y se hace uso del debug para observar las variables
paso por referencia se puede visualizar en la figura 7, donde en la ventana watch como se puede apreciar en al figura 9
Figura 9. Resultados de la simulación del algoritmo desarrollado

En la figura previa se puede ver entonces 6! = 720, aunque


n=1, pues este n es el valor final con el cual termina una
vez realizado todo el proceso de recursividad como se puede
observar en la figura 8 m=1, la cuestión es entonces porque m
y n tiene el mismo valor, se debe a que se ha usado el paso por
referencia, por lo tanto n queda con el valor de m; lo mismo
ocurre con fR, que ya al haberse usado paso por referencia el
valor que tenga f0 sera el mismo para fR. Figura 10. Diagrama de flujo del algoritmo a desarrollar

II-D. Desarrolle un programa que permita obtener los 20


Con base en el diagrama de flujo, se realiza el programa en
primeros polinomios de Legendre (el valor de x=2).
el software Code Composer Studio,y en la ventana watch se
saca las 20 posiciones del puntero pL como se muestra en la
Previo a realizar el desarrollo del programa se debe conocer figura 11
cuales son los polinomios de Legendre; estos polinomios
estan definidos de forma general por la siguiente expresión :

(2n − 1) ∗ x ∗ P(n − 1) − (n − 1)P(n − 2)


Pn(x) =
n

Donde : n = Polinomio que se desea hallar y x = variable


dada.

Los dos primeros polinomios (n=0 y n=1) para cualquier


valor de x son :

Po(x) = 1.
P1(x) = x.

Ahora se procede a hacer el diagrama de flujo correspon-


diente, el cual se puede observar en la figura 10, donde se
Figura 11. Resultados de la simulación del algoritmo desarrollado
definen la variable x=2, n=20 y un putero(*pL) que apunta a un
arreglo(L) de 20 posiciones, luego se llenan las dos primeras
posiciones de manera manual como se analiza en el párrafo
anterior y posteriormente con un condicional el cual limita
a obtener solamente los primero 20 polinomios de Legendre Sin embargo, con el fin de verificar los polinomios de Le-
utilizando la expresión general y teniendo en cuenta desde gendre obtenidos; por medio de Matlab se realiza la expresión
posición(n=2) obteniendo ası́ los valores desde pL[0] hasta general en un ciclo for teniendo en cuenta que matlab indexa
pL[19] desde 1. Este resultado se puede apreciar en la figura 12
las cuales se usaran para realizar las diferentes operaciones
y 4 vectores de 4 posiciones(S,R,M,I) los cuales tendrán los
resultados. Posteriormente se realiza el llamado de todas las
funciones por paso por referencia, donde las operaciones
estarán dadas ası́ :

Suma : S = A + B
Resta : R = A - B
Multiplicación : M = C*D
Inversa : I = inv(E)

Teniendo las matrices de la figura 14:

Figura 12. Resultados de la simulación del algoritmo desarrollado en Matlab

Como se puede observar concuerdan con los valores de los


polinomios en de la ventana watch
II-E. Crear una cabecera de C que realice la multiplicación,
suma, resta e inversa de una matriz de 2X2. Verifique su
funcionamiento.
Primero se debe tener presente que para crear una cabecera,
se deben crear 2 archivos : uno .c y otro .h; donde el de
extensión .h es aquel donde se declaran las funciones, y el
de extensión .c es donde se implementan, es decir, que hacen
dichas funciones. Este archivo .c no tiene main.

Se procede a realizar lo que corresponde a el diagrama de


flujo, el cual puede ser visualizado en la figura 13.

Figura 14. Matrices de entrada para comprobar el algoritmo desarrollado

Se obtienen los resultados de la figura 15:

Figura 15. Matrices de resultados para comprobar el algoritmo desarrollado

Figura 13. Diagrama de flujo del algoritmo a desarrollar

En primera instancia, el diagrama principal incluye la El diagrama Cinco.h es bastante sencillo, solo tiene las
librerı́a Cinco.h y se definen 4 matrices de 2x2 (A,B,C,D,E) funciones declaradas y se puede observar en la figura 16
se puede apreciar en la figura 18

Figura 16. Matrices de entrada para comprobar el algoritmo desarrollado

El diagrama Cinco.c es donde se implementan todas las


funciones y se puede observar en la figura 17
Figura 18. Matrices de entrada para comprobar el algoritmo desarrollado

Por otro lado, el diagrama de flujo de la multiplicación


es una expresión general obtenida a partir de un análisis
matemático y se observa en la figura 19. Por último el
diagrama de flujo de la inversa tiene determinado de forma
manual el determinante y la matriz adjunta transpuesta, para
luego realizar la división entre estos; dicho diagrama se puede
visualizar en la figura 20

Figura 17. Matrices de entrada para comprobar el algoritmo desarrollado

Ademas cada función tiene su propio diagrama de flujo:

El diagrama de flujo de la suma es igual al de la resta,


simplemente se suma o se resta punto a punto; este diagrama Figura 19. Matrices de entrada para comprobar el algoritmo desarrollado
free : Limpia la memoria.

Con esto en cuenta, se realiza el respectivo diagrama de


flujo el cual puede ser visualizado en la figura 22.

Figura 20. Matrices de entrada para comprobar el algoritmo desarrollado

Con base al diagrama de flujo se realiza el programa en el


software Code Composer Studio, donde se puede observar
en la ventana watch los resultados obtenidos. Dicha ventana
se puede apreciar en la figura 21

Figura 22. Diagrama de flujo del algoritmo a desarrollar

Como se observa en el diagrama, se definen 2 punteros


tipo double, para el primero puntero(*F) se reservan 8
posiciones de memorias con el comando malloc, pero es
Figura 21. Resultados de la simulación del algoritmo desarrollado indispensable tener en cuenta el type casting(double*) de
puntero para que quede float, pues el comando malloc
Se puede observar que los resultados son correctos, si se devuelve un entero tipo bol; luego se llenan las primera
comparan con los resultados apreciados en la figura 15. 8 posiciones del puntero con el factorial 1 a 8 respectivamente.

II-F. Crear un arreglo de 8 posiciones llenarlo con el fac- Luego, se aumenta tamaño con el comando realloc
torial de 1 a 8 respectivamente, luego en tiempo de ejecución utilizando el puntero *tmpF, es decir, aumenta hasta tamaño
redimensionarlo a 14 y llenar los datos que están vacı́os con 14 el puntero F teniendo en cuenta que son espacios de
sus respectivos factoriales. memoria de tamaño double, y de nuevo se debe tener en
Para realizar la redimensión de un arreglo es necesario cuenta el type casting. Por último un condicional para
trabajar y acceder al monton/heap que es la memoria determinar si la memoria es insuficiente(tmpF=NULL), si no
dinámica, para ello se hace a través de punteros y ademas es es el caso entonces se iguala F=tmpF y se llenan las restantes
necesario trabajar con los siguientes comandos : posiciones del puntero(hasta la 14) y finalmente se limpia la
memoria con el comando free(F); llegando el caso a tener
malloc : Reserva posiciones de memoria. memoria insuficiente se sale del programa(exit(-1)).
realloc : Aumenta o disminuye el tamaño.
Posteriormente se realiza el programa en el software Code En este diagrama, se puede observar que se definen 3
Composer Studio, a través del debug se obtiene la ventana buffer de 100 posiciones tipo double, el valor pi(3.1416) y
watch que corresponde a la figura 23 una varible iterativa (i). Simplemente de forma iterativa, es
decir, a través de condicionales se llenan las 100 posiciones
del buffer y con la función seno, con una amplitud de 5 y una
f = 100 Hz; asi mismo se llena las 100 posiciones del buffer
x pero utilizando la función coseno. Por último se llena el
buffer r que corresponde a la suma posición por posición del
buffer y y el buffer x.

Ahora se procede a realizar el programa en el software Code


Composer Studio, a través del debug se observan los datos
en la ventana watch como se aprecia en la figura 25

Figura 23. Resultados de la simulación del algoritmo desarrollado

Donde se puede observar las posiciones 0 hasta la 13 del


puntero F, y que corresponden exactamente a los factoriales
p[0] = 1! hasta p[13] = 14!. Ademas, es importante notar que
hay memoria suficiente.

II-G. Crear dos buffer en el primero se debe almacenar


la función seno y el segundo la función coseno, por ultimo
realizar la suma de estos dos buffer.
Previo al desarrollo del programa, se realiza el diagrama
de flujo correspondiente a las exigencias del enunciado. Este
diagrama de flujo puede ser visualizado en la figura 24.

Figura 25. Resultados de la simulación del algoritmo desarrollado en Matlab

Como se puede observar de la figura previa, se tiene el


buffer de salida(r) tipo double 100 posiciones, pero al ser
tantos valores no se pueden apreciar todos en una imagen.
De manera que para verificar el resultado(r), se hace uso de
las herramientas graficas del software siguiendo los pasos a
continuación:

Figura 24. Diagrama de flujo del algoritmo a desarrollar Tools - Graph - Single Time :
Figura 28. Resultados gráficos de la simulación del algoritmo desarrollado

Se puede comprobar entonces que graficamente r[0] = 5, al


igual que lo es en la ventana watch de la figura 25
III. CONCLUSIONES
La recursividad no puede proporcionar un ahorro en
almacenamiento, puesto que en algun lugar se debe mantener
una pila de los valores procesados. Ni será mas rapida.
Figura 26. Pasos para el uso de la herramienta gráfica del software Sin embargo, el código recursivo es más compacto y
frecuentemente mucho más facil de escribir y de entender
que su equivalente no recursivo.
Graph Properties
Hasta un tamaño moderado de programa, probablemente
es mejor tener un archivo de encabezamiento(cabecera) que
contenga todo lo que será compartido entre las partes del
programa. Para un programa mucho más grande, se necesitará
más organización y mas archivos de cabecera.

Utilizar una función tipo paso por valor para cierto


algoritmo ocasiona una replica de datos, usando doble
espacio de memoria. Sin embargo, si se realiza función de
paso por referencia, no replica los datos debido a que no pasa
el dato, sino la posición de memoria que es global.

El uso de memoria dinamico(heap), proporciona la ventaja


frente a la memoria estatica(stack) de que puede variar su
tamaño durante la ejecución del programa; es necesario cuando
no se conoce el número de datos a tratar.
IV. BIBLIOGRAFIA
[1].BRIAN W KERNIGHAN, DENNIS M RITCHIE, El
lenguaje de Programación C. 2ed. Mexico DF: Prentice Hall,
1991 .

Figura 27. Pasos para el uso de la herramienta gráfica del software

Una vez realizado esto, debe aparecer en la ventana consola


la grafica que se muestra en la figura 28. La cual representa
el buffer r(suma entre el seno y el coseno).

También podría gustarte