Herramientas de usuario

Herramientas del sitio


introduccion

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anteriorRevisión previa
Próxima revisión
Revisión previa
introduccion [2012/07/31 14:04] – [Comparación entre C y Java] lmateuintroduccion [2020/03/08 21:05] (actual) lmateu
Línea 7: Línea 7:
 ===== Historia ===== ===== Historia =====
  
-  * En los 50's nace el primer lenguaje de programación: Fortran (//Formula Translator//).  La idea era poder escribir fórmulas algebraicas cómodamente sin tener que escribir en lenguaje ensamblador.  No hay while ni if/else: se usa if ... goto. +  * En los 50's nace Fortran, el primer lenguaje de programación "de alto nivel".  El objetivo era bastante modesto, ya que solo se buscaba poder escribir fórmulas algebraicas cómodamente sin tener que programarlas en lenguaje ensamblador.  Sin embargo todavía no hay while ni if/else: se usa if ... goto.  La programación es no estructurada.  Por eso su sigla significa //Formula Translator//
-  * En los 60's surge el primer lenguaje con programación estructurada: Algol.  Posee while e if/else.  Es un lenguaje demasiado complejo para las máquinas de la época. De este lenguaje se derivan 2 variantes minimalistas, Pascal y C, que sí son implementables. +  * En los 60's surge el primer lenguaje para la programación estructurada: Algol.  Posee while e if/else.  Es un lenguaje demasiado complejo para las máquinas de la época. De este lenguaje se derivan 2 variantes, Pascal y C, que sí son implementables. 
-  * En los 70'aparece Pascal (de Niklaus Wirth).  Busca la robustez en la programación.  Es un lenguaje minimalista. +  * Pascal aparece en los 70's (de Niklaus Wirth).  Busca la robustez en la programación.  Es un lenguaje minimalista. 
-  * También en los 70'aparece C (de Brian Kernighan).  La sintaxis es distinta de Algol y Pascal. recible la flexibilidad del manejo de memoria del assembler para así poder programar un sistema operativo (Unix) en un lenguaje de alto nivel (C).  Por eso no puede ser robusto, aunque sí es minimalista.+  * C también aparece en los 70's (de Brian Kernighan).  La sintaxis es distinta de Algol y Pascal. recibe la flexibilidad del manejo de memoria del assembler para así poder programar un sistema operativo (Unix) en un lenguaje de alto nivel (C).  Por eso no puede ser robusto, aunque sí es minimalista.
   * A fines de los 70's aparece el primer lenguaje orientado a objetos: Smalltalk.  Es puro, todo es un objeto.  Es minimalista, pero es extremadamente ineficiente porque debe ser interpretado.   * A fines de los 70's aparece el primer lenguaje orientado a objetos: Smalltalk.  Es puro, todo es un objeto.  Es minimalista, pero es extremadamente ineficiente porque debe ser interpretado.
-  * En los 80's Bjarne Stroustrup enriquece C con clases para facilitar la programación orienta a objetos en un lenguaje eficiente, dando así origen al lenguaje C++.  Tampoco es robusto y es complejo.+  * En los 80's Bjarne Stroustrup enriquece C con clases para facilitar la programación orientada a objetos en un lenguaje eficiente, dando así origen al lenguaje C++.  Tampoco es robusto y es complejo
 +  * A fines de los 80 Guido Van Rossum concibe Python como en lenguaje de programación fácil de usar.  Favorece la escritura rápida de programas pero sacrificando la eficiencia en tiempo de ejecución: Un programa en Python puede requerir de 10 a 100 veces más tiempo de ejecución que el mismo reescrito en C.
   * En los 90's James Gosling concibe Java como una forma de darle robustez a C++.  Es menos complejo que C++.   * En los 90's James Gosling concibe Java como una forma de darle robustez a C++.  Es menos complejo que C++.
  
-===== Ejemplo de pograma en C =====+===== Ejemplo de programa en C =====
  
 Ejemplo estudiado: [[http://www.dcc.uchile.cl/jpiquer/Docencia/cc31a/copy.c|copy.c]] Ejemplo estudiado: [[http://www.dcc.uchile.cl/jpiquer/Docencia/cc31a/copy.c|copy.c]]
Línea 44: Línea 45:
   * Entrega una constante caracterizada como EOF cuando llega al final del archivo.   * Entrega una constante caracterizada como EOF cuando llega al final del archivo.
   * putchar es otra función estándar de C que escribe un caracter en la salida estándar.   * putchar es otra función estándar de C que escribe un caracter en la salida estándar.
-  * El include al inicio del archivo es una directiva para el procesador.  Indica que se debe agregar en ese punto textualmente el archivo stdio.h.  Este contiene declaraciones de funciones de E/S típicamente usadas como getchar, putchar, printf.  Y constantes como EOF.+  * El include al inicio del archivo es una directiva para el preprocesador.  Indica que se debe agregar en ese punto textualmente el archivo stdio.h.  Este contiene declaraciones de funciones de E/S típicamente usadas como getchar, putchar, printf. definiciones de constantes como EOF.
   * Observe que una asignación puede aparecer en cualquier lugar en donde es válido colocar una expresión porque = es un operador como +, *, etc.  No es usual que en Java un argumento de una expresión sea una asignación, pero en C sí lo es.   * Observe que una asignación puede aparecer en cualquier lugar en donde es válido colocar una expresión porque = es un operador como +, *, etc.  No es usual que en Java un argumento de una expresión sea una asignación, pero en C sí lo es.
  
Línea 68: Línea 69:
 </code> </code>
  
-  * Todo programa en Unix tiene una entrada estándar y una salida estñandar.+  * Todo programa en Unix tiene una entrada estándar y una salida estandar.  Usualmente son el teclado y la pantalla respectivamente.
   * Además existe una salida estándar de errores.   * Además existe una salida estándar de errores.
-  * La entrada estándar se especifica con '<' seguido del nombre del archivo. +  * La entrada estándar se puede redirigir usando el símbolo '<' seguido del nombre del archivo. 
-  * La salida estándar se especifica con '>' seguido del nombre del archivo. +  * La salida estándar se pude redirigir usando el símbolo '>' seguido del nombre del archivo. 
-  * Si no se especifica entrada o salida estándar se usa la del shell que corresponde usualmente a teclado y consola respectivamente.+  * El símbolo '|' es para crear pipes.  En un pipe la salida estándar del comando de la izquierda se conecta con la entrada estándar del comando de la derecha.
   * Entonces los archivos out, out2 y out3 todos son iguales.   * Entonces los archivos out, out2 y out3 todos son iguales.
  
Línea 79: Línea 80:
 <code> <code>
 % ./copy < out > out4 % ./copy < out > out4
-% echo $status+% echo $?
 1 1
 % %
Línea 85: Línea 86:
  
   * El 1 es el código de retorno y es el valor retornado por main.  Cambie 'return 1' por 'return 2' y rehaga el experimento.   * El 1 es el código de retorno y es el valor retornado por main.  Cambie 'return 1' por 'return 2' y rehaga el experimento.
-  * El shell almacena en la variable $status el código de retorno del último programa ejecutado.+  * El shell almacena en la variable $el código de retorno del último programa ejecutado.
  
 ===== Comparación entre C y Java ===== ===== Comparación entre C y Java =====
Línea 94: Línea 95:
   * El compilador de C (comandos gcc o cc) produce archivos con instrucciones de máquina en binario que son directamente ejecutables por la máquina.   * El compilador de C (comandos gcc o cc) produce archivos con instrucciones de máquina en binario que son directamente ejecutables por la máquina.
   * El compilador de Java (comando javac) produce archivos '.class' que corresponden a instrucciones de una máquina virtual (la JVM: java virtual machine).  Para ejecutarlos se invoca el comando java que incluye un compilador JIT (just in time) que traduce en memoria las instrucciones virtuales a las intrucciones de la plataforma usada.  Al no generar un archivo con la traducción, la compilación JIT ocurre cada vez que se ejecuta el programa.   * El compilador de Java (comando javac) produce archivos '.class' que corresponden a instrucciones de una máquina virtual (la JVM: java virtual machine).  Para ejecutarlos se invoca el comando java que incluye un compilador JIT (just in time) que traduce en memoria las instrucciones virtuales a las intrucciones de la plataforma usada.  Al no generar un archivo con la traducción, la compilación JIT ocurre cada vez que se ejecuta el programa.
-==== Generalidades ==== 
  
-  * Los archivos en C llevan las extensión '.c' mientras que en Java '.java'. 
-  * El compilador de C (comandos gcc o cc) produce archivos con instrucciones de máquina en binario que son directamente ejecutables por la máquina. 
-  * El compilador de Java (comando javac) produce archivos '.class' que corresponden a instrucciones de una máquina virtual (la JVM: java virtual machine).  Para ejecutarlos se invoca el comando java que incluye un compilador JIT (just in time) que traduce en memoria las instrucciones virtuales a las intrucciones de la plataforma usada.  Al no generar un archivo con la traducción, la compilación JIT ocurre cada vez que se ejecuta el programa. 
 ==== Programación orientada a objetos ==== ==== Programación orientada a objetos ====
  
Línea 125: Línea 122:
 ^ ^ Java ^ C ^ ^ ^ Java ^ C ^
 | declaración | <code>Node p;</code> | <code>Node *p;</code> | | declaración | <code>Node p;</code> | <code>Node *p;</code> |
-| asignación de memoria | <code>p= new Node();</code> | <code>p= (Node*)malloc(sizeof Node);</code>|+| asignación de memoria | <code>p= new Node();</code> | <code>p= malloc(sizeof Node);</code>|
 | acceso | <code>Node q= p.next;</code>     | <code>Node *q= p->next;</code> | | acceso | <code>Node q= p.next;</code>     | <code>Node *q= p->next;</code> |
 | destrucción |                                  | <code>free(p);</code> | | destrucción |                                  | <code>free(p);</code> |
Línea 138: Línea 135:
   * Un error frecuente en C es el puntero loco o colgante (dangling reference).  Ocurre cuando equivocadamente se libera la memoria, pero todavía está siendo referenciada.   * Un error frecuente en C es el puntero loco o colgante (dangling reference).  Ocurre cuando equivocadamente se libera la memoria, pero todavía está siendo referenciada.
   * Otro error frecuente en C es la gotera de memoria: cuando un trozo de memoria pedido con malloc nunca se libera.   * Otro error frecuente en C es la gotera de memoria: cuando un trozo de memoria pedido con malloc nunca se libera.
-  * En Java el recolector de basura evita por completo los punteros locos.  Usualmente se piensa que también evita las goteras, pero no esto no es cierto.  Las reduce pero no las evita.  Un típico caso es poblar una tabla de hash con objetos que nunca serán consultados.  Esos objetos sí son goteras.+  * En Java el recolector de basura evita por completo los punteros locos.  Usualmente se piensa que también evita las goteras, pero esto no es cierto.  Las reduce pero no las evita.  Un típico caso es poblar una tabla de hash con objetos que nunca serán consultados.  Esos objetos sí son goteras.
   * En C el puntero nulo es NULL en mayúscula.  En Java es null en minúsculas.   * En C el puntero nulo es NULL en mayúscula.  En Java es null en minúsculas.
  
Línea 146: Línea 143:
   * No se debe llamar a malloc.  El espacio de memoria requerido se asigna automáticamente al ingresar a la función.   * No se debe llamar a malloc.  El espacio de memoria requerido se asigna automáticamente al ingresar a la función.
   * Se accede a los campos con el operador '.': <code>node.next</code>  No se usa '->'.   * Se accede a los campos con el operador '.': <code>node.next</code>  No se usa '->'.
-  * La variable se destruye automáticamente al retornar de la función.+  * La variable se destruye automáticamente al retorno de la función.
   * Se puede asignar la dirección de la variable a un puntero: <code>Node *p= &node;</code>   * Se puede asignar la dirección de la variable a un puntero: <code>Node *p= &node;</code>
   * Un error típico es acceder al contenido de p después del retorno de la función en donde se declaró node.   * Un error típico es acceder al contenido de p después del retorno de la función en donde se declaró node.
-  * Como Java es un lenguaje robusto, para evitar este error simplemente en Java no se pueden declarar variables de tipos compuestos locales a una función.  Por eso en Java se eliminó el uso de '*' pues //todas las variables de tipo compuesto son punteros//+  * Como Java es un lenguaje robusto, para evitar este error simplemente en Java no se pueden declarar variables de tipos compuestos locales a una función.  Por eso en Java se eliminó el uso de '*' pues //todas las variables de tipo compuesto son punteros//. 
 + 
 +==== Instrucciones ==== 
 + 
 +Java heredó las todas las instrucciones de control de C y por lo tanto las siguientes construcciones sintácticas 
 +funcionan igual que en Java: 
 + 
 +  * flujo condicional: **if** (//cond//) //inst_1// **else** //inst_2// 
 +  * ciclo normal: **while** (//cond//) //inst// 
 +  * variante de ciclo: **do** { //inst// ... } **while** (//cond//); 
 +  * ciclo for: **for** ( //ini// ; //cond//; //incr//) //inst// 
 +  * agrupar instrucciones: { //decl// ... //inst// ... } 
 +  * **switch** (//exp//) { //const// : //inst// ... **break**; ... **default**: //inst// ... } 
 + 
 +Pero se debe tener cuidado si el compilador implementa una versión de C anterior al estándar C99, como por ejemplo ansi-C. 
 + 
 +Antes de C99 el ciclo for no admite declarar la variable de control en la misma expresión de inicialización.  Por ejemplo el siguiente código es ilegal: 
 + 
 +<code> 
 +  for (int i=0; i<10; i++) 
 +    ... 
 +</code> 
 + 
 +La forma correcta es: 
 + 
 +<code> 
 +  int i; 
 +  ... 
 +  for (i=0; i<10; i++) 
 +    ... 
 +</code> 
 + 
 +Además las declaraciones de variables antes de C99 siempre debían ir al comienzo de un bloque { ... }.  Por ejemplo era ilegal: 
 + 
 +<code> 
 +  int i;        /* declaración */ 
 +  i= getchar(); /* no es una declaración */ 
 +  int j;        /* error de sintaxis, porque no viene después de una declaración */ 
 +  j= ...; 
 +</code> 
 + 
 +Pero este código sí es correcto: 
 + 
 +<code> 
 +  int i= getchar(); /* sí es declaración */ 
 +  int j;            /* otra declaración */ 
 +  j= ...; 
 +</code> 
 + 
 +A partir de C99 sí se admiten declaraciones en cualquier punto y declaraciones en el ciclo for. 
 + 
 +==== Funciones ==== 
 + 
 +La sintaxis para declarar un función es la misma de los métodos de Java, solo que una función no está contenida en la declaración de una clase.  Por ejemplo, la función que calcula el factorial recursivamente es: 
 + 
 +<code> 
 +  /* Archivo fact.c */ 
 +  double fact(int n) { 
 +    if (n<=1) 
 +      return 1; 
 +    else 
 +      return n*fact(n-1); 
 +  } 
 +</code> 
 + 
 +Para usar esta función en otro archivo se debe declarar un prototipo o encabezado de la función previamente: 
 + 
 +<code> 
 +  /* Archivo main.c */ 
 +  double fact(int n);  /* prototipo o encabezado de la función fact */ 
 +   
 +  int main(int argc, char **argv) { 
 +    double res= fact(atoi(argv[1]));  /* invoca la función fact */ 
 +    printf("%e\n", res); /* despliega el resultado en la salida esstándar */ 
 +    return 0; 
 +  } 
 +</code> 
 + 
 +  * una función solo es conocida a partir del momento en donde se declara la función o se declara su encabezado. 
 +  * no existen los atributos de visibilidad como private, public o protected. 
 +  * normalmente las funciones son conocidas en todos los archivos, a condición que se declare previamente un prototipo de la función. 
 +  * si se antepone el atributo static, la función es solo conocida en el archivo en donde está declarada. 
 + 
 +==== Archivos de encabezado ==== 
 + 
 +Declarar los encabezados de la funciones en cada archivo en donde se usa es peligroso porque si uno se equivoca en el tipo de los parámetros o el valor de retorno, el compilador no avisa y el resultado es imprevisible.  La solución 
 +es crear archivos que contengan solo los encabezados de un grupo de funciones.  Estos archivos de encabezado 
 +tienen la extensión ".h" y normalmente se incluyen al inicio de los archivos en donde se usan la funciones incluidas. 
 + 
 +Para el ejemplo anterior, el archivo de encabezado sería: 
 + 
 +<code> 
 +  /* archivo fact.h */ 
 +  double fact(int n); 
 +</code> 
 + 
 +Y el archivo en donde se usa: 
 + 
 +<code> 
 +  /* Archivo main.c */ 
 +  #include "fact.h" 
 +   
 +  /* no declarar un encabezado para fact */ 
 +   
 +  int main(int argc, char **argv) { 
 +    double res= fact(atoi(argv[1]));  /* invoca la función fact */ 
 +    printf("%e\n", res); /* despliega el resultado en la salida esstándar */ 
 +    return 0; 
 +  } 
 +</code> 
 + 
 +Previo a la verdadera compilación de un archivo, el compilador invoca el preprocesador de C (llamado cpp) 
 +que se encarga de expandir literalmente los #include reemplazándolos por el contenido del archivo con los 
 +encabezados. 
 + 
 +De esta forma, uno se debe preocupar solamente de la consistencia de los parámetros de la función declarada 
 +con los parámetros que aparecen en el archivo de encabezados ".h" Esto reduce considerablemente la probabilidad de error. 
introduccion.1343743447.txt.gz · Última modificación: 2012/07/31 14:04 por lmateu