← C EspañolChapter 13 of 13

Mejores Prácticas

## Objetivos de Aprendizaje - Escribir código C limpio y mantenible - Seguir convenciones de nomenclatura - Dominar técnicas de depuración - Aplicar pruebas efectivas ## Estilo de Código ### Convenciones de Nomenclatura ```c // Variables: snake_case int user_age; char *file_name; size_t buffer_size; // Constantes: UPPER_SNAKE_CASE #define MAX_BUFFER_SIZE 1024 const int MAX_RETRIES = 3; // Funciones: snake_case int calculate_total(void); void process_data(const char *input); // Tipos/Estructuras: snake_case con sufijo _t typedef struct { int x; int y; } point_t; ``` ### Formato ```c // Usar 4 espacios para indentación // Longitud de línea: ~80 caracteres máximo // Una declaración por línea int age; char *name; size_t count; // Llaves siempre if (condition) { do_something(); } else { do_other(); } // Declaraciones de funciones int main(void) { return 0; } ``` ## Inicialización ### Siempre Inicializar Variables ```c // Mal - contiene basura int count; // Bien - explícitamente inicializado int count = 0; // Bien - inicializado a cero int *ptr = NULL; char buffer[100] = {0}; ``` ### Inicializar Punteros a NULL ```c // Buena práctica int *ptr = NULL; // Verificar antes de desreferenciar if (ptr != NULL) { *ptr = 42; } ``` ## Gestión de Memoria ### Siempre Liberar Memoria ```c int *ptr = (int*)malloc(sizeof(int)); if (ptr == NULL) { return 1; } // Usar memoria... free(ptr); ptr = NULL; // Prevenir puntero colgante ``` ### Verificar Asignación ```c int *ptr = (int*)malloc(sizeof(int)); if (ptr == NULL) { // Manejar error fprintf(stderr, "Allocation failed\n"); return 1; } ``` ### Liberar en Orden Inverso ```c // Si se asignan nodos enlazados struct Node *n1 = malloc(sizeof(struct Node)); struct Node *n2 = malloc(sizeof(struct Node)); n1->next = n2; // Liberar en orden inverso free(n2); free(n1); ``` ## Funciones ### Usar const para Parámetros de Solo Lectura ```c // Bien - indica que str no se modifica size_t stringLength(const char *str) { size_t len = 0; while (str[len] != '\0') { len++; } return len; } ``` ### Retornar Códigos de Error ```c typedef enum { SUCCESS = 0, ERROR_NULL_POINTER = 1, ERROR_OUT_OF_MEMORY = 2, ERROR_INVALID_INPUT = 3 } error_code_t; error_code_t processData(const char *input, int *output) { if (input == NULL || output == NULL) { return ERROR_NULL_POINTER; } // Procesar... return SUCCESS; } ``` ### Las Funciones Pequeñas Son Buenas ```c // Bien - responsabilidad única int isEven(int x) { return x % 2 == 0; } int isOdd(int x) { return x % 2 != 0; } ``` ## Arreglos y Cadenas ### Cálculo de Tamaño ```c int arr[10]; size_t size = sizeof(arr) / sizeof(arr[0]); ``` ### Verificación de Límites ```c int getElement(const int *arr, size_t size, size_t index) { if (index >= size) { // Manejar error return 0; } return arr[index]; } ``` ### Terminar Cadenas en NULL ```c char buffer[100]; strncpy(buffer, input, sizeof(buffer) - 1); buffer[sizeof(buffer) - 1] = '\0'; ``` ## Manejo de Errores ### Verificar Valores de Retorno ```c FILE *fp = fopen("file.txt", "r"); if (fp == NULL) { perror("Failed to open file"); return 1; } // Usar archivo... if (fclose(fp) != 0) { perror("Failed to close file"); return 1; } ``` ### Usar assert para Depuración ```c #include void process(int *data, size_t size) { assert(data != NULL); assert(size > 0); // Procesar... } ``` ### Desactivar en Producción ```c #define NDEBUG // Antes de #include #include ``` ## Comentarios ### Usar Comentarios con Sabiduría ```c // Bien: explica POR QUÉ, no QUÉ // Saltar primera línea (contiene encabezado) if (line[0] == '#') { continue; } // Mal: redundante int i = 0; // Inicializar i a 0 ``` ### Documentar Funciones ```c /** * Calcula la suma de dos enteros. * * @param a Primer entero * @param b Segundo entero * @return Suma de a y b */ int add(int a, int b) { return a + b; } ``` ## Portabilidad ### Tipos de Tamaño Fijo ```c #include int32_t i32 = 42; // Exactamente 32 bits uint64_t u64 = 100; // Exactamente 64 bits sin signo intptr_t ptr = (intptr_t)&x; // Contiene puntero ``` ### Evitar Suposiciones Sobre Tamaño ```c // Mal - asume 4 bytes long x = 1000000; // Bien - usar tamaño fijo o límite int32_t x = 1000000; ``` ### Impresión Portátil ```c #include int64_t big = 9000000000000000000LL; printf("%" PRId64 "\n", big); ``` ## Seguridad ### Evitar Desbordamiento de Buffer ```c // Mal - posible desbordamiento de buffer char buffer[100]; gets(buffer); // Bien - entrada segura fgets(buffer, sizeof(buffer), stdin); buffer[strcspn(buffer, "\n")] = '\0'; ``` ### Validar Entrada ```c if (strlen(input) >= MAX_INPUT) { // Manejar error } ``` ### Usar Funciones de Cadena Seguras ```c // Usar strncpy en lugar de strcpy strncpy(dest, src, sizeof(dest) - 1); dest[sizeof(dest) - 1] = '\0'; // Usar strncat en lugar de strcat strncat(dest, src, sizeof(dest) - strlen(dest) - 1); ``` ## Pruebas ### Ejemplo de Pruebas Unitarias ```c #include int add(int a, int b) { return a + b; } void testAdd(void) { assert(add(2, 3) == 5); assert(add(-1, 1) == 0); assert(add(0, 0) == 0); assert(add(-5, -5) == -10); } int main(void) { testAdd(); printf("All tests passed!\n"); return 0; } ``` ## Depuración ### valgrind ```bash valgrind --leak-check=full ./program ``` ### Advertencias de gcc ```bash gcc -Wall -Wextra -Werror -pedantic program.c -o program ``` | Bandera | Descripción | |---------|-------------| | `-Wall` | Activar todas las advertencias | | `-Wextra` | Advertencias adicionales | | `-Werror` | Tratar advertencias como errores | | `-pedantic` | Conformidad ISO C | | `-g` | Incluir símbolos de depuración | | `-O2` | Optimizar (para pruebas de rendimiento) | ## Rendimiento ### Evitar Optimización Prematura ```c // Código claro primero for (int i = 0; i < n; i++) { sum += arr[i]; } // Optimizar solo si profiling muestra que es necesario ``` ### Usar Funciones Inline (C99) ```c inline int max(int a, int b) { return a > b ? a : b; } ``` ## Resumen - Usar nombres significativos (snake_case para variables) - Siempre inicializar variables - Verificar valores de retorno de asignación - Liberar memoria y establecer a NULL - Usar const para parámetros de solo lectura - Activar advertencias del compilador (-Wall -Wextra) - Usar valgrind para detectar fugas de memoria - Escribir pruebas para funciones críticas - Validar toda la entrada - Usar tipos de tamaño fijo para portabilidad

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →