Tipos incompletos y punteros opacos – c

Pregunta:


He visto artículos en ingles que hablan sobre esto, según he logrado entender se usan para encapsulación en C. Alguien puede explicar que es exactamente un tipo incompleto y un puntero opaco? Y cuales usos tienen en C?

Preguntado por: cheroky

NaCl

Un típo incompleto es como su nombre lo indica, un típo sin definición, lo que es complementado con los punteros opacos, consideremos el siguiente ejemplo:

fecha.h

typedef struct date date_t;
unsigned get_hours(date_t *dt);

//... Resto de funcionalidades

fecha.c

typedef struct date {
    // implementación de la estructura.
} date_t;

Tienes una implementación opaca al proveer sólo la declaración de la estructura de datos date_t, permitiendo al usuario de tu librería sólo un puntero a la estructura y un conjunto de funciones para darle comportamiento.

Todo se define en el archivo de código que será compilado para entregar el binario a quién lo use.

Estas implementaciones se utilizan para mantener el código lo más oculto posible frente a los usuarios finales, de esta forma no saben el contenido del puntero internamente.

Al final:

  • Puntero opaco: Es un puntero a una estructura que desconocemos (4 u 8 bytes) que no sabemos lo que contienen ni su tamaño real.
  • Típo incompleto: Típo que sólo ha sido declarado pero no definido frente a los ojos del usuario final.

Un ejemplo práctico:

/* date_t.h */
#ifndef DATE_T_HEADER
#define DATE_T_HEADER

/* declaración opaca */
typedef struct date date_t;

/* algunos métodos */
date_t *new_date(void);
unsigned get_hours(date_t *dt);
void set_hours(date_t *dt, unsigned t);
unsigned get_difference_seconds(date_t *dt1, date_t *dt2);
void delete_date(date_t *dt);

#endif /* DATE_T_HEADER */

/* date_t.c */
#include <stdlib.h>
#include <stdio.h> 
#include "date_t.h"

/* Definición de la estructura */
typedef struct date {
    size_t time;
    char holamundo;
} date_t; /* FAIL PADDING, sizeof esta estructura es 16 u 8 ... */

date_t *new_date(void) {
    date_t *ptr = malloc(sizeof(struct date));
    return ptr;
}
unsigned get_hours(date_t *dt) {
    if (dt) return dt->time;
    return 0;
}
void set_hours(date_t *dt, unsigned t) {
    if (dt) dt->time = t;
}
unsigned get_difference_seconds(date_t *dt1, date_t *dt2) {
    if (dt1 && dt2) return dt1->time - dt2->time;
    return 0;
}
void delete_date(date_t *dt) {
    if (dt) { 
        free(dt); 
        dt = NULL;
    }
}

/* test.c */
#include <stdio.h>
#include "date_t.h"

int main(void) {
    date_t *ptrdate = new_date();
    printf("Nueva fechanAjustando a 55 las horas...n");
    set_hours(ptrdate, 55);
    if (get_hours(ptrdate) == 55)
        printf("En efecto es 55.n");
    date_t *se = new_date();
    printf("Creada nueva fecha...n");
    set_hours(se, 10);
    printf("Diferencias: %un", get_difference_seconds(ptrdate, se));
    delete_date(ptrdate); delete_date(se);
}

Notese que ha sido de cabeza por lo que puede no funcionar del todo (Pendiente hasta que encuentre mi ordenador).

Probar con la siguiente línea de comandos para obtener resultado:

> gcc -o date.o -c -std=c11 date.c 
> gcc -o test.o -c -std=c11 test.c
> gcc -o test *.o

Debe arrojar el siguiente resultado:

Nueva fecha
Ajustando a 55 las horas...
En efecto es 55.
Creada nueva fecha...
Diferencias: 45

SN1: -std=c11 porque nunca hay que perder el estilo.

Para finalizar, las principales ventajas de implementar este tipo de opacidad en C es que limitas la cantidad de cambios que los usuarios son capaces de hacerle a tu estructura, lo cual tiene un efecto colateral, dado que no todos quieren hacer las cosas a tu manera, pero la implementacion es util a la hora de realizar software para vender.

Y como todo en C, no es bueno abusar de este tipo de metodologia.

1: Side note.

Fuente

Related Posts:

Declarar un array de structs de tamaño dinamico – c++
Pregunta: buenas, lo que quiero conseguir es declarar un struct con array que tenga su tamaño dinamico, pero cuando lo hago el programa se me ...
Problemas con el registro de un archivo .tlb – c# windows vb6
Pregunta: La situación es la siguiente: He creado un pequeño proyecto de librería de clases en C# que me permita realizar ciertas operaciones. El nombre del ...
Uso de js y c# en unity. ¿Igual rendimiento? – javascript c# unity3d
Pregunta: Estoy comenzando con unity . Y veo que se pueden usar c# y js para programar. Mi pregunta es si tanto c# como js ...
Cómo puedo incluir librería beecrypt en un proyecto en C – c
Pregunta: Tengo un archivo .lib (librería) y quiero usarla en un proyecto de C. Para ser más especifica estoy intentando instalar beecrypt que es una librería ...
Ocultar y Mostrar con Mapa de Google – javascript c# asp.net
Pregunta: Tengo un div en mi página ASP.NET que contiene un Mapa de Google, y necesito mostrarlo y ocultarlo pero no me funciona. Este es el ...
para que sirve #ifdef_MSDOS_ en c++? – c++
Pregunta: He tenido problemas porque donde trabajo usan una versión de dev c++ 4.9 y yo uso en mi hogar la 5.1, ...
¿Como instalar C# en SublimeText? – c# sublimetext3 sublimetext
Pregunta: El problema es que actualmente quiero programar sobre esta tecnologia, pero no quiero descargar aun el visual studio porque consume recursos y es bastante ...
Thread en c++ error compilacion – c++
Pregunta: Estoy empezando con threads y he estado siguien varios tutos y creo que esta todo bien, pero a la hora de ejecutarlo me da ...
¿Es posible capturar un segfault con try/catch? – c++ try-catch
Pregunta: Para comprobar si es posible hice lo siguiente: try { int *x = 0; *x = 1234; } catch(...) { ...
Conexion C# con PostgreSQL mediante proveedor Npgsql – c# postgresql
Pregunta: Hola el problema es que la conexión esta bien solo cuando estoy utilizando el ODBC, pero cuando lo cambio al proveedor de PostgreSQL Npgsql, ...
Construcción extraña: objeto = funcion1() && funcion2() ¿Posible? – c#
Pregunta: acabo de encontrarme en una documentación una construcción como esta: var pose = Body.LeftHand.Near(Body.Head) && Body.LeftArm.Bended(90); posees una objeto que debe crearse a partir de la ...
Cómo importar datos de un Excel a DataGrid pero iniciarlo en la segunda fila? – c# sql-server postgresql
Pregunta: Disculpen una duda, como cargar de excel un formato iniciando en la segunda fila? tengo este código solamente que el excel esta justificado en ...
No completa el ciclo foreach – c#
Pregunta: Estoy haciendo un método para invertir palabras que contengan 5 o mas letras. El problema que tengo es que si mi cadena tiene mas ...
Obtener elementos específicos de un array – c array optimización
Pregunta: Buenas, si yo por ejemplo hago: char buf; fgets(buf, 1024, stdin); ¿Puedo coger los caracteres que escribí del array sin coger los elementos que no utilicé? ¿O ...
Averiguar número de elementos en un array de LUA – c++ array lua
Pregunta: ¿Cómo puedo averiguar el número de elementos que contiene un array en un fichero LUA? me gustaría poder volcarlo a un entero desde C++. -- ...
Tags:

Add a Comment

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *