Red de conocimiento informático - Aprendizaje de código fuente - Changping Beida Jade Bird comparte las ventajas y desventajas de la tecnología de programación en lenguaje C

Changping Beida Jade Bird comparte las ventajas y desventajas de la tecnología de programación en lenguaje C

Con el desarrollo continuo de la tecnología de programación de Internet, la mayor parte del desarrollo de software ahora se implementa a través de lenguajes de programación. Hoy veremos las ventajas y desventajas de la tecnología de desarrollo de programación en lenguaje C.

Algunas buenas experiencias usando el lenguaje C

Aprenda a implementar programación orientada a objetos en lenguaje C leyendo el código fuente de POV-Ray una vez.

Comprenda la claridad, simplicidad y mantenibilidad del código C leyendo el código fuente GTK+.

Aprenda a implementar el analizador Scheme en lenguaje C leyendo el código fuente de SIOD y Guile.

Versión inicial escrita de GNOMEEye en C y renderizado MicroTile ajustado.

Algunas experiencias desagradables con C

Cuando estaba en el equipo de Evolution, muchas cosas seguían rompiéndose. En aquel entonces no existía Valgrind y para utilizar Purify como programa era necesario comprar una máquina Solaris.

Depurar el problema de bloqueo de subprocesos de gnome-vfs.

Error al depurar Mesa.

Se hizo cargo de la versión inicial de Nautilus-share, solo para descubrir que free() en realidad no se usaba en el código.

Quiero refactorizar el código, pero no sé cómo gestionar bien la memoria.

Quería empaquetar el código, pero descubrí que había variables globales en todas partes pero no funciones estáticas.

De todos modos, hablemos de cosas que Rust tiene y C no.

Gestión automatizada de recursos

Rust toma prestadas ideas como RAII (ResourceAcquisitionIsInitialization, inicialización de adquisición de recursos) y punteros inteligentes de C++, y agrega el principio de propiedad única de valores, al tiempo que proporciona automatización. Mecanismo de gestión de recursos para la toma de decisiones.

Automatización: No es necesario llamar manualmente a free(). La memoria se liberará automáticamente después de que se agote, el archivo se cerrará automáticamente después de que se agote y el bloqueo mutex se liberará automáticamente después de que salga del alcance. Si desea encapsular recursos externos, básicamente simplemente implementa Drop como una característica. Los recursos encapsulados son como parte del lenguaje de programación porque no es necesario gestionar su ciclo de vida.

Determinista: crea recursos (asignación de memoria, inicialización, archivos abiertos, etc.) y luego los destruye fuera del alcance. No hay recolección de basura: cuando se ejecuta el código, todo termina. El ciclo de vida de los datos del programa es como un árbol de llamadas a funciones.

Si siempre me olvido de llamar a estos métodos (liberar/cerrar/destruir) cuando escribo código, o me doy cuenta de que el código que escribí antes se olvida de llamar a estos métodos, o incluso llama al error, entonces no lo hago. Ya no quiero usar estos métodos.

Genérico

Vec es en realidad un vector de elementos T, no solo una matriz de punteros de objetos. Después de la compilación, solo se puede utilizar para contener objetos de tipo T.

Hacer algo como esto en C requeriría mucho código, así que no quiero hacerlo más.

Los rasgos no son solo interfaces

Rust no es un lenguaje de programación orientado a objetos; tiene rasgos, y los rasgos en Rust parecen interfaces: se pueden usar para implementar enlaces dinámicos. . Si un objeto implementa un Drawable, debe tener un método draw().

Pero en cualquier caso, los rasgos hacen mucho más que eso.

Gestión de dependencias

Anteriormente, implementar la gestión de dependencias requería:

Invocar g-config manualmente o mediante una macro de herramienta automatizada.

Básicamente se requiere un esfuerzo humano para garantizar que esté instalada la versión correcta de la biblioteca.

En Rust, por otro lado, simplemente escribe un archivo Cargo.toml y especifica las versiones de las bibliotecas dependientes en el archivo. Estas bibliotecas dependientes se descargarán u obtendrán automáticamente desde una ubicación específica.

Probar

Las pruebas unitarias en C son muy difíciles por las siguientes razones:

Las funciones intrínsecas suelen ser estáticas. Es decir, no se pueden llamar desde archivos externos. Los programas de prueba deben usar directivas #include para incluir archivos fuente o usar #ifdefs para eliminar estas funciones estáticas durante las pruebas.

Es necesario escribir un Makefile para vincular el programa de prueba a algunas bibliotecas dependientes o parte del código que contiene.

Necesita utilizar un marco de pruebas, registrar casos de prueba en él y aprender a utilizarlos.

Macros de higiene

Las macros de higiene de Rust evitan problemas asociados con las macros de C, como la posibilidad de que el contenido dentro de la macro pueda ocultar los identificadores en el código. Rust no requiere paréntesis para todos los símbolos en macros, como max(5+3,4).

Sin conversión automática

En C, Chambers descubrió que muchos errores se debían a la conversión inadvertida de ints a short o chars, lo que no sucedió en Rust. Este es el caso porque Rust requiere. conversión explícita.

Sin desbordamiento de enteros

Esto no requiere más explicaciones.