I.5. Código = Datos + Instrucciones.

Variables y Funciones.

Declaración de variables [OBLIGATORIA en C++]

Si recuerdas la práctica 3, obteníamos un error porque std y cout no estaban declarados.
Debemos pensar nuevamente que todo en el ordenador son 0 y 1: programas, texto, imagenes,... Para que mi ordenador sepa que la sucesión "0001101010101110" en una determinada posición de la memoria es un número y no una letra o un punto en una foto,... debemos indicarle que tipo de dato es y asignarle un nombre a ese espacio de memoria que nos permita su uso posterior.
Esto se denomina declaración de una variable y se realiza así:

tipo_dato identificador;

con esta instrucción el ordenador reserva un espacio en la memoria para almacenar un dato del tipo_dato, esto es almacena una sucesión de 1 y 0, y obliga a que las operaciones con esa variable sean compatibles con el tipo de datos.

Inicialización de variables

Cuando el programa asigna memoria a una variable, en el paso anterior, reserva espacio y nada más, por ejemplo, al declarar una variable numérica, el valor inicial no es necesariamente 0, sino que puede ser cualquier cosa.
Así que es muy recomendable, de hecho si no lo hacemos el compilador nos avisa, realizar una asignación a una variable, antes de usarla. Una asignación se realiza así:

identificador = valor;

donde valor puede ser una expresión más o menos compleja.
Usamos una variable cuando esta participa en el lado derecho de una asignación (precisamente en "valor") o como valor en una función.

Pero vayamos a la práctica
Práctica 5: Este sería el texto de nuestro main.cc , comentado

/* Created by Anjuta version 1.2.4a */
/*    This file will not be overwritten */

#include <iostream>
int main()
{  
    int x;  // declaración de la variable x
    x=12; // inicialización de x
    int y=64; // declaración e inicialización de y en un solo paso
    std::cout << "X= " << x << " Y= " << y << std::endl;    // ver resultados en la pantalla
    char z; //declaración de la variable z  
    std::cout<<"Z = "<<z<<std::endl; // ATENCION z se usa antes de asignarle un valor, genera un aviso del compilador
    x=x+y;  // asignación típica 
    std::cout << "------después de x=x+y--------" << std::endl<<std::endl;
    std::cout << "X= " << x << " Y= " << y << std::endl;
    z=y; // ¿?
    std::cout << "------después de z=y--------" << std::endl<<std::endl;
    std::cout<<"Z = "<<z<<std::endl;// Aquí esta instrucción ya no provoca aviso del compilador.

    return 0;
}


Graba el archivo, compila (F11) y ... ejecuta (F3). No debiera haber problemas.
Las variables x e y son declaradas del tipo int (número entero) [es un tipo predefinido de C y C++]. Cabe destacar que y se declara e inicializa en un solo paso, de la siguiente forma: 

int y=64;

con esto, reservamos en la memoria del ordenador espacio suficiente para almacenar una secuencia de  0 y 1, las cuales serán interpretadas como dos números enteros, uno recibirá el nombre de 'x' y otro el de 'y'.  

Luego declaramos z como char ( carácter )[otro dato predefinido].
Observa que como z es usada en la línea siguiente (std::cout<<...<<z...)antes de ser inicializada, obtenemos el correspondiente mensaje de advertencia, aunque nos permite ejecutar el programa. Las inicializaciones no son obligatorias pero si altamente recomendables, en un programa complejo podíamos tener errores difíciles de detectar.
Sin embargo, tras la asignación z=y; la variable queda inicializada y la misma instrucción anterior ya no provoca un aviso del compilador.

Por cierto, y se le ha asignado el valor 64 (01000000) y a z se le asigna dicho valor (01000000), pero z es declarada como char, así que cuando mandamos presentarla por pantalla aparece la famosa @. Si buscas los códigos ascii, verás que la @ es el código nº 64 (¡qué coincidencia!).

NOTA:
Normalmente, en C y C++ la asignación de tipos es advertida, o incluso da error (pruebe a sustituir int y por double y -double es una forma de declarar variables numéricas reales- observarás  un aviso).


x=x+y;

Esta última instrucción puede resultar extraña para un matemático (sin conocimientos informáticos) pero es muy utilizada en programación. Indica al ordenador que sume los valores de las variables 'x' e 'y' (12+64) y el resultado lo almacene nuevamente en 'x'. 'x' e 'y' se pueden sumar porque han sido definidas como variables numéricas, y la suma es una operación definida entre variables numéricas.



Práctica 6:
En C y C++, es fundamental, considerar los tipos de variables. El siguiente programa muestra la diferencia entre dividir dos enteros (resultado un entero) y dividir dos números enteros, considerándolos como reales.


#include <iostream>

int main()
{    int x=23;
    int  y=12;
    std::cout << "int X/Y = " << x/y << std::endl;
    std::cout << "double X/Y = " << (double)x/(double)y << std::endl;   
    return 0;
}


(double)x es una operación denominada cast, que viene a significar que le decimos al compilador que la variable no es real, pero que creemos que se trate como tal.

;

toda instrucción de C++ termina con un punto y coma [;].
Aun cuando no lo parezca, este programa es igual al de la práctica anterior:
#include <iostream>
int
main() {    int x=23;     int  y=12;     std::cout << "int X/Y = " << x/y << std::endl;
    std::cout << "double X/Y = "
<<                      (double)x/(double)y               <<
 std::endl;   
    return
0;
}


Las tabulaciones, retornos,... son una cuestión estética y para facilitar la lectura a nosotros (que no es poco), pero no afecta al código objeto compilado.

Es un error frecuente (en mi caso mucho más) olvidarse de colocar un ';' al final de una instrucción.

¿Pero... #include?
Ciertamente la línea de #include no tiene un ';' , esto es así porque no es código ejecutable en sí, es una directiva para que al compilar el archivo previamente se incluya el código del archivo específicado. Por ello se les denomina directivas del preprocesador, y se reconocen porque vienen precedidas por el símbolo #.
¿ y main?
Como veremos las funciones son una agrupación de código entre dos llaves {...}, dentro de ellas existen instrucciones ejecutables (con sus respectivos ;), pero ellas en sí no lo son. 

Declaración de Funciones

Las funciones son un conjunto de instrucciones que cumplen una función determinada (valga la redundancia), son el alma de la programación y para poder utilizarse  deben: declararse y definirse.
Al igual que con los datos en C y C++ antes de usarse una función ésta debe declararse, lo cual se hace tal que así:

tipo_dato_devuelto nombre_función ([argumentos]);

Los argumentos son opcionales porque existen funciones como las funciones main que estamos utilizando que no tienen argumentos. Cuando una función tiene argumentos, en la declaración es suficiente con indicar el tipo de datos que recibe; si son varios estos se separan por coma [,]


A veces una función no precisa devolver dato alguno, lo que en otros lenguajes denominan subrutinas. En C y C++ no existen subrutinas, y las funciones que no devuelven se declaran del tipo void.

NOTA: en mis experiencias con Ubuntu, la función main() es siempre de tipo int, y no puede definirse como de tipo void. Aunque he leído por ahí que si, a mí me da error.

La declaración de función le dice al compilador que determinada función va a ser utilizada, verificando que el uso de la misma se haga adecuadamente o sino muestre un aviso o un error.

Todas las funciones deben declararse antes de utilizarse, ¿todas? todas menos una [main]. Las declaraciones suelen estar en los archivos de cabecera (.h), y se incluyen con la directiva #include.

Definición de funciones

La definición consiste en el desarrollo de la función, el código en sí. Las definiciones están en los archivos fuente (.cc,.cpp,.c). Tienen una estructura similar a la declaración, de hecho, si una función es definida con anterioridad a main

tipo_dato_devuelto nombre_función ([argumentos]){ Instrucciones}

A diferencia de la declaración, la definición requiere que los argumentos vengan declarados, es decir no sólo indican el tipo, también el identificador. En la declaración, también puede ponerse el identificador pero no es estrictamente necesario.  Pero mejor con un ejemplo.
Práctica 7: Modifiquemos el programa de esta forma:

/* Created by Anjuta version 1.2.4a */
/*    This file will not be overwritten */

#include <iostream>
int suma (int,int); //declaración de la función, los argumentos sin identificador
int main()
{    int x,y;
    x=12;
    y=10;
    std::cout << "X= " << x << " Y= " << y << std::endl;
    x=suma(y,y); // USO de la función
    std::cout << "------después de x=x+y--------" << std::endl<<std::endl;
    std::cout << "X= " << x << " Y= " << y << std::endl;
    return 0;
}
int suma (int x, int y) //definición de la función, los argumentos con identificador
{
    return x+y;
}
NOTA: Recuerda que para compilar de nuevo es suficiente pulsar F11, y luego F3.
Pero ANTES es necesario GRABAR el archivo.
int suma (int,int);

Es la declaración de la función, o más exactamente el prototipado, le dice al compilador que se va a utilizar una función denominada suma, que acepta dos valores de tipo integer, y devuelve como resultados de la operación otro integer.
(prueba a borrar esta línea y compila el proyecto... te aparecerá un mensaje de error diciéndote que suma no es conocida en el ámbito de main)

int suma (int x, int y)
{
    return x+y;
}

Es la definición de la función, donde se encuentra el código, en este caso una única instrucción. 

x=suma(y,y);

Es una asignación que llama a la función suma con dos parámetros y el resultado de esta es asignado a la variable x. Aquí tras suma si ponemos ; porque no se está definiendo sino que se esta ejecutando.

ATENCIÓN: Observa que la 'x' e 'y' de main, y la 'x' e 'y' de suma son diferentes.  Llamamos a suma con dos 'y'-de main-, esto es  suma (10, 10). A la variable 'x' de la función suma, y a la 'y', se le asigna el valor 10, por lo que el resultado devuelto es 20.
return es una palabra clave utilizada para devolver el valor. En nuestra función devuelve la suma de las dos variables, y en el caso de main devuelve 0 (0 es el valor utilizado para comunicar al sistema que el programa a terminado con éxito, se pueden devolver otros valores).
Como he expuesto si una función es definida con anterioridad a main(), también es declarada:
El siguiente archivo da error, la función no es declarada y se define con posterioridad a main() Este archivo no da error, la función suma es definida, y por tanto declarada, antes que main()
#include <iostream>

int main() {   
    int x= 12;
    int z= 10;
   
    x=suma(z,x);
    std::cout<<x;
    return 0;
}

int suma (int x,int y){
    return x+y;
}
#include <iostream>

int suma (int x,int y){
    return x+y;
}

int main() {   
    int x= 12;
    int z= 10;
   
    x=suma(z,x);
    std::cout<<x;
    return 0;
}
C++, algo más que un paso más que C
Indice