Incomplete types and opaque pointers

5

I have seen articles in English that talk about this, as I have understood they are used for encapsulation in C. Can someone explain that it is exactly an incomplete type and an opaque pointer? And what uses do they have in C?

    
asked by cheroky 26.04.2017 в 22:07
source

1 answer

5

An incomplete type is as its name indicates, a type without definition, which is complemented with opaque pointers, consider the following example:

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;

You have an opaque implementation by providing only the declaration of data structure date_t , allowing the user of your library only a pointer to the structure and a set of functions to give it behavior.

Everything is defined in the code file that will be compiled to deliver the binary to whoever uses it.

These implementations are used to keep the code as hidden as possible from the end users, so they do not know the contents of the pointer internally.

At the end:

  • Opaque pointer: It is a pointer to a structure that we do not know (4 or 8 bytes) that we do not know what they contain or their actual size.
  • Incomplete type: Typically only declared but not defined in the eyes of the end user.

A practical example:

/* 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 fecha\nAjustando 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: %u\n", get_difference_seconds(ptrdate, se));
    delete_date(ptrdate); delete_date(se);
}

Note that it has been upside down so it may not work at all (Pending until I find my computer) .

Try using the following command line to get results:

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

You should throw the following result:

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

SN 1 : -std=c11 because you never have to lose the style.

To conclude, the main advantages of implementing this type of opacity in C is that you limit the amount of changes that users are able to make to your structure, which has a side effect, since not everyone wants to do things to your way, but the implementation is useful when making software to sell.

And like everything in C, it is not good to abuse this type of methodology.

1 : Side note.

    
answered by 26.04.2017 / 23:24
source