Operaciones Binarias, Manejo de Memoria y Estructuras en C

Este documento detalla conceptos fundamentales de programación en C, incluyendo operaciones a nivel de bit, manipulación de memoria, manejo de cadenas y la estructura de datos de pila (stack).

Operaciones a Nivel de Bit Las operaciones a nivel de bit manipulan los datos en su representación binaria. Los operadores clave son:

  • << (Desplazamiento a la izquierda): Mueve los bits de un número a la izquierda, rellenando con ceros a la derecha.
  • >> (Desplazamiento a la derecha): Mueve los bits de un número a la derecha. El comportamiento para números con signo puede variar (relleno con signo o cero).
  • & (AND a nivel de bit): Devuelve 1 en una posición de bit si ambos operandos tienen 1 en esa posición.
  • | (OR a nivel de bit): Devuelev 1 en una posición de bit si al menos uno de los operandos tiene 1.
  • ^ (XOR a nivel de bit): Devuelve 1 en una posición de bit si los operandos tienen bits diferentes en esa posición.
  • ~ (NOT a nivel de bit): Invierte todos los bits del operando.

Representación de Números Los números enteros en C se almacenan internamente utilizando el complemento a dos:

  • Representación directa (源码): La representación binaria estándar del número. Para negativos, el bit más significativo indica el signo.
  • Complemento a uno (反码): Se obtiene invirtiendo todos los bits de la representación directa (para positivos) o invirtiendo los bits excepto el signo (para negativos).
  • Complemento a dos (补码): Se obtiene sumando 1 al complemento a uno. Todos los números (positivos y negativos) se almacenan en memoria como complemento a dos. Los números positivos tienen la misma representación directa, complemento a uno y complemento a dos.

Manejo de Datos y Memoria

Conversión y Tamaño de Datos

  • La función strlen() (de <string.h></string.h>) se utiliza para determinar la longitud de una cadena de caracteres (sin incluir el carácter nulo terminador).
  • La función sizeof() se usa para obtener el tamaño en bytes de un tipo de dato o variable.

Estructuras y Punteros Las estructuras permiten agrupar variables de diferentes tipos bajo un mismo nombre. Los punteros se utilizan para referenciar la dirección de memoria de estas estructuras.

struct DatosUsuario {
    char nombre[50];
    int edad;
    char genero[10];
    int identificador;
};

struct DatosUsuario usuario1 = {"Ana López", 25, "Femenino", 1001};
struct DatosUsuario usuario2;

struct DatosUsuario* ptrUsuario = &usuario1; // Puntero a usuario1

// Acceso a través del puntero usando el operador ->
printf("Nombre del usuario: %s\n", ptrUsuario->nombre);

// Acceso a través del puntero usando desreferenciación y operador punto
printf("Edad del usuario: %d\n", (*ptrUsuario).edad);

// Para modificar un campo a través del puntero:
strcpy(usuario1.nombre, "Ana Garcia"); // strcpy es de <string.h>
printf("Nombre modificado: %s\n", usuario1.nombre);

Gestión de Memoria y Alcance

  • Las variables locales declaradas dentro de una función residen en la pila (stack). Las direcciones de estas variables no son válidas una vez que la función termina.
  • El uso de la palabra clave static para una variable local extiende su ciclo de vida hasta el final del programa, manteniendo su valor entre llamadas a la función. La varible se almacenará en la memoria estática en lugar de la pila.
  • Los datos asignados dinámicamente en el montículo (heap) usando malloc, calloc, etc., persisten hasta que se liberan explícitamente con free.

Funciones de Utilidad

Validación de Punteros La macro assert() (de <assert.h></assert.h>) se utiliza para verificar condiciones durante la ejecución. Si la condición es falsa, el programa termina y se muestra un mensaje de error.

char* buffer = obtenerDatos(); // Asume que esta función podría devolver NULL
assert(buffer != NULL && "Error: No se pudieron obtener los datos.");
// Continuar si buffer no es NULL

Ordenamiento (Quick Sort) La función qsort() (de <stdlib.h></stdlib.h>) implementa el algoritmo de ordenamiento rápido. Requiere una función de comparación personalizada.

// Función de comparación para enteros
int compararEnteros(const void* elem1, const void* elem2) {
    int val1 = *(const int*)elem1;
    int val2 = *(const int*)elem2;
    if (val1 < val2) return -1;
    if (val1 > val2) return 1;
    return 0;
}

// Ejemplo de uso
int numeros[] = {5, 2, 8, 1, 9};
size_t tamano = sizeof(numeros) / sizeof(numeros[0]);
qsort(numeros, tamano, sizeof(int), compararEnteros);

printf("Array ordenado: ");
for (size_t i = 0; i < tamano; ++i) {
    printf("%d ", numeros[i]);
}
printf("\n");

// Función de comparación para flotantes (con manejo de precisión)
int compararFlotantes(const void* elem1, const void* elem2) {
    float val1 = *(const float*)elem1;
    float val2 = *(const float*)elem2;
    if (val1 < val2) return -1;
    if (val1 > val2) return 1;
    return 0;
}

Alineación de Estructuras La directiva de preprocesador #pragma pack() se puede usar para controlar la alineación de los miembros de una estructura, lo cual afecta el tamaño y la disposición en memoria.

#pragma pack(push, 1) // Establece la alineación a 1 byte
struct PaqueteDatos {
    char tipo;        // 1 byte
    int valor;        // 4 bytes (en sistemas de 32 bits)
    short id;         // 2 bytes
};
#pragma pack(pop) // Restaura la alineación predeterminada

// offsetof (de <stddef.h>) se usa para obtener el desplazamiento de un miembro
struct EjemploAlineacion {
    char c1;       // Offset 0
    int i;         // Offset 4 (si la alineación por defecto es 4)
    double d;      // Offset 8 (si la alineación por defecto es 8)
};

// printf("Offset de c1: %zu\n", offsetof(struct EjemploAlineacion, c1));
// printf("Offset de i: %zu\n", offsetof(struct EjemploAlineacion, i));
// printf("Offset de d: %zu\n", offsetof(struct EjemploAlineacion, d));

La alineación de estructuras puede afectar el rendimiento y el uso de memoria. El compilador generalmente añade bytes de relleno (padding) entre miembros para asegurar que cada miembro comience en una dirección de memoria que sea múltiplo de su tamaño o de la alineación natural del procesador.

Etiquetas: C Programación de Sistemas operaciones a nivel de bit Punteros Estructuras

Publicado el 6-24 18:51