Disponible la versión 6 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


1.3.1  Estructura lógica.

Part of the problem is that programming is hard to teach. “Programming is a mixture of a highly technical skill and an aesthetic art. And that’s a very difficult combination.” James Maguire en su artículo "The 'Anti-Java' Professor and the Jobless Programmers". Basado en una entrevista con Robert Dewar, profesor emérito de Ciencia de la Computación en New York.

§1  Sinopsis

Desde el punto de vista lógico, puede considerarse que los programas comprenden dos tipos de elementos diferentes: estructuras de datos y algoritmos. O dicho en otras palabras: datos, e instrucciones para su manipulación. Su representación codificada adopta dos formas: una entendible por la máquina (ejecutable y ficheros de datos) y otra entendible por el humano (fuente). Para el conjunto de ambas puede considerarse una escala conceptual que, si vamos de lo general a lo particular, podemos representarla como sigue:

Nota:  clasificaciones como la que aquí proponemos solo tiene una finalidad didáctica; son un vehículo para introducir al lector en la comprensión global del concepto y no un asunto dogmático e inamovible, ya que este tipo de asuntos depende grandemente del punto de vista que se adopte.  Como botón de muestra, vaya por delante la definición de lo que es un programa en palabras de Ellis y Stroustrup [6 §3.3], que por lo demás ofrece un punto de vista muy interesante: "Un programa consiste en uno o más ficheros enlazados juntos. Un fichero consiste en una secuencia de declaraciones" (ver Declaraciones y definiciones en 4.1.2).  A continuación admiten que esta afirmación puede parecer extraña a aquellos acostumbrados a pensar en un programa como una serie de sentencias ejecutables acompañadas de las declaraciones de las variables correspondientes.  Pero recuerdan que en C++, las sentencias están contenidas en funciones, y que en realidad, el cuerpo de una función es en sí mismo una declaración (de la propia función). En consecuencia, puesto que las declaraciones pueden contener inicializadores, también deben ser consideradas como "ejecutable" (lo que hemos denominado algoritmo).

§2  Aplicación

Comprende ejecutables y datos. Puede haber múltiples ficheros de ambos tipos (ficheros de datos y ejecutables).

   

§3  Programa

Parte de una aplicación (código) que puede cargarse y ejecutarse independientemente.

   

§4  Fichero fuente:

Se llaman así (abreviadamente) los ficheros que contienen el código fuente (ficheros .C / .CPP) escrito por el programador. Un "fuente" se compila de una vez, cuando recibe la acción del preprocesador ( 1.4.1), dando lugar a lo que técnicamente se denomina unidad de compilación ( 1.4.2).  Un solo fuente puede ser dividido en múltiples ficheros, cada uno de los cuales puede contener varias funciones, aunque la inversa no es cierta: una función no puede ser dividida entre varios fuentes.

La mayoría de las aplicaciones de cierto porte ocupan más de un fuente. Los diversos ficheros son creados y mantenidos por distintos programadores. Después, los ficheros son compilados y enlazados para producir una aplicación final.

Es conveniente recordar que C y C++ se desarrollaron en ambientes UNIX, por lo que desde su cuna son lenguajes sensibles a las mayúsculas/minúsculas ("case sensitive") [3]. Esto no representa inconveniente para los programadores acostumbrados a entornos Unix/Linux, pero suele ser fuente de errores para los que han desarrollado en Sistemas MS-DOS y Windows donde esta distinción no es tan importante. Por ejemplo, en C++ la declaración

int X, x;

declara dos variables distintas.

   

§5  Función:

Una parte de un programa (subrutina) con un nombre, que puede ser invocada (llamada a ejecución) desde otras partes tantas veces como se desee. Opcionalmente puede recibir valores (argumentos);  se ejecuta y puede devolver un valor ( 4.4).

main ( 4.4.4) es la primera función en cualquier programa C++; es llamada desde unas rutinas especiales "de inicio" que se incluyen automáticamente en todo programa C++. Esta función es el punto de inicio del programa desde el punto de vista del programador (donde este toma el control).

 

§6  Bloque

Lista, que puede estar vacía, de sentencias delimitadas por corchetes { } ( 3.2.6).  Desde el punto de vista sintáctico, un bloque puede ser considerado como una sola sentencia (sentencia compuesta 4.10). Dentro de las posibilidades de memoria, los bloques pueden ser anidados a cualquier nivel (los bloques pueden contener otros bloques).  El aspecto de los bloques "anidados" es como sigue:

...         // espacio global del fichero

main {      // comienzo del bloque main

  ....      // espacio del bloque main

  {         // bloque anidado

    ...     // espacio del bloque anidado

  }         // fin de bloque

  ....

}           // fin del bloque main

 

§7  Sentencia

Si establecemos una analogía entre un lenguaje natural y un lenguaje computacional como C++, podemos afirmar que las sentencias ("Statements") juegan en C++ el mismo papel que las oraciones en el lenguaje natural, y del mismo modo que una oración gramatical es una palabra o conjunto de ellas, con que se expresa un sentido gramatical completo [4], las sentencias se componen de una o varias expresiones y tienen sentido computacional completo.

La sentencia es la unidad lógica completa más simple en un programa;  en C/C++  terminan en punto y coma ;.  Un caso especial es la expresión nula ( ; aislado). En el apartado 1.3.1a se describe su sintaxis y en el capítulo 4.10 se ofrece su definición formal y una clasificación de los distintos tipos que existen en C++. 

Un caso especial lo componen las directivas de preprocesado ( 4.9.10), que suponen transformaciones en el fuente por parte del preprocesador ( 1.4.1).

  

§8  Expresión

Siguiendo en sentido ascendente de simplicidad en el lenguaje natural, después de las oraciones están las frases, Conjunto de palabras que basta para formar sentido, especialmente cuando no llega a constituir una oración cabal [5]. Su equivalente en el lenguaje C++ serán las expresiones.

Las expresiones son secuencias de tokens (operadores, operandos y elementos de puntuación) que especifican una computación; tienen sentido computacional en sí mismas.  Son los bloques de computación más simples con los que se construye un programa  [6 §5] aunque no pueden ejecutarse separadamente sino cuando forman una sentencia.

Como verá el lector, la diferencia entre sentencia y expresión es algo arbitraria. Una o varias expresiones terminadas en punto y coma constituyen una sentencia.  Desde el punto de vista lógico, cada sentencia se ejecuta de una vez (aunque sus expresiones sean evaluadas individualmente siguiendo ciertas reglas ).  En el programa suele estar muy claro cual es el orden de ejecución de sus sentencias, no así de sus expresiones dentro de ellas, toda vez que el Estándar es permisivo en algunos aspectos de detalle.

Es importante señalar que, en contra de lo que ocurre en otros lenguajes, en C/C++, el final de línea no significa necesariamente el fin de la expresión, de forma que esta puede ocupar más de una línea (en realidad el compilador ignora los pares de caracteres CR/LF que añaden los editores al final de línea). Por ejemplo:  la expresión

int x = 5*(4+(3/2-1))

puede ser escrita como:

int x =
    5*
      (
        4+
        (3/2-1)
      );


  Los conocedores de otros lenguajes advertirán que en C++ no tiene sentido la barra inclinadas \ con que otros lenguajes indican que la siguiente línea de código es en realidad una continuación de la anterior. Se exceptúa naturalmente el caso de constantes de cadena, donde si es preciso indicar al compilador que, en su caso, la cadena continúa en la línea siguiente. Ejemplo, aunque es correcto escribir:

int  x =

   5;

En cambio es incorrecto poner

char* string = "Las constantes de cadena pueden tener

cualquier longitud";

En este caso es necesario indicar al compilador que la cadena continúa en la línea siguiente:

char* string = "Las constantes de cadena pueden tener \

cualquier longitud";


Del mismo modo que los gramáticos distinguen varios tipos de frases (hecha, musical, proverbial, etc), los informáticos distinguen también varios tipos de expresiones. Los ejemplos que siguen son meramente ilustrativos y no pretenden ser una relación completa:

  • De asignación:  Si tienen uno, o varios, operadores de asignación ( 4.9.2).  Ejemplos:

    x += 3;

    z = y = x/2;

  • Declarativas:  Si dan a conocer un identificador al compilador ( 4.1.2). Ejemplos:

    extern int funcX(int x, char c);

    class MiClase;

  • Definiciones:  Establecen la creación de un objeto reservándole espacio físico.  Ejemplo:

    int x = 2;

    MiClase c1 (x, y, z);

  • Condicionales:  Definen alternativas de acción en el programa. Ejemplos:

    int y = 6 ? 7: 8;

    if (salida = 'S') break;

  • De salto:  Obligan al programa a seguir en un sitio distinto de la secuencia natural (la siguiente sentencia). Ejemplos:

    break;

    continue;

  • Bitwise.  De manejo y comparación de bits ( 4.9.3). Ejemplos:

    x | y;
    x << 2;

Las expresiones pueden producir un Lvalue ( 2.1.5), un Rvalue ( 2.1.6) o ningún valor.  Ejemplo:

int x;    // no produce ningún valor

x = 2;    // produce un valor (resultado)

Además de producir un valor, las expresiones pueden tener efectos laterales (tanto si producen un valor como si no lo producen). Ejemplo:

x = ++a;

Además de producir un valor (un resultado 4.9.2), esta expresión tendría dos efectos laterales:

:  Incrementar en 1 el valor de a,

:  Asignar el valor modificado de a a la variable x.

El "resultado" de la expresión coincide precisamente con el valor de x [2].

Las expresiones se evalúan siguiendo ciertas reglas de conversión [1], agrupamiento, asociatividad y precedencia ( 4.9).  Estas reglas dependen de varios factores:  el operador;  la naturaleza de los operandos utilizados en cada caso, y de la presencia de paréntesis en la expresión ( 4.9.0a). En el apartado 1.3.1b se describe completamente su sintaxis formal así como su precedencia y asociatividad. Su sintaxis muestra que las expresiones son definidas recursivamente, y que las subexpresiones pueden ser anidadas sin ningún límite formal.

  

§9  Token

Los tokens ( 3.2) son los elementos en que el preprocesador desmenuza el código fuente. En un lenguaje de programación, los tokens son el equivalentes al conjunto de las  palabras y signos de puntuación en el lenguaje natural escrito.

En el lenguaje C++ estas "palabras" pueden ser de varios tipos: palabras claveidentificadoresconstantesoperadoressignos de puntuación (puntuadores) y comentarios (son eliminados). Los tokens están separados por elementos de separación que reciben el nombre genérico de separadores ("Whitespaces").

  Inicio.


[1]  Los métodos utilizados en las conversiones aritméticas estándar se han detallado en 2.2.5

[2]  Esta característica: producir un resultado, de las expresiones de asignación, es lo que posibilita la existencia en C++, de expresiones como:

x = y = z+1;

[3]  Me encantaría conocer una versión española de esta palabra inglesa.

[4] Este es el sentido gramatical de la palabra oración según el Diccionario Usual de la Real Academia de la Lengua Española.  Según el Diccionario de Uso del Español de María Moliner, la oración es la unidad más pequeña de lenguaje organizado gramaticalmente. Si nos referimos al lenguaje natural, conceptualmente la oración consta de dos partes:  un sujeto del que se dice o afirma algo, y un predicado, que es lo que se dice del sujeto,  y puede ser de dos clases, nominal y verbal. Es nominal cuando lo que se dice del sujeto está contenido en un nombre o adjetivo, es verbal cuando lo que se dice del sujeto está contenido fundamentalmente en un verbo.

[5]  Este es el sentido de la palabra "frase" según el Diccionario de la Real Academia de la Lengua Española.

[6]  Stroustrup & Ellis:  ACRM.