Strona 1 z 1

Opaque Pointer czyli wskaźnik jakby opakowany.

: czwartek 12 lip 2018, 23:20
autor: xor
Niezłą metodą na ukrycie szczegółów implementacyjnych modułu programowego przed światem zewnętrznym jest wykorzystanie wskaźników.

Strukturę danych deklarujmy w pliku .c a wiec tylko tam będą widoczne jej szczegóły.

Kod: Zaznacz cały

/*   opak.c   */

#include "opak.h"

//struktura która będzie ukryta pod "opakowanym" wskaźnikiem
typedef struct Opak  {
   int ene;
   char due;
   char *like;
   long fake;
} Opak;

//Konkretne instancje obiektu Opak zaalokowane statycznie
Opak opakObjOne;
Opak opakObjTwo;

//funkcja operująca na obiekcie Opak
void jakasMetoda(Opak * const opak)
{
...
}


Plik nagłówkowy pokazuje tylko to co niezbędne. Co prawda użycie zmiennych extern kłóci się z zasadą "najlepsza zmienna globalna to taka przed którą umieszczone są dwa slasze", ale w tym wypadku nie wiadomo nic o ich typie więc kompilator nie pozwoli na jakiekolwiek, a prawdopodobnie nieporządane, operacje na zmiennych (oczywiście poza operacjami za pośrednictwem dostarczonych metod).

Kod: Zaznacz cały

/*   opak.h   */

//deklaracje obiektów Opak, których struktura jest całkowicie niewidoczna
extern struct Opak opakObjOne;
extern struct Opak opakObjTwo;

//deklaracja metody operującej na obiekcie Opak
void jakasMetoda(struct Opak * opak);



Niepełna deklaracja typu Opak nie przeszkadza w użyciu danych o tym typie, ale tylko w operacjach dozwolonych (czyli za pomocą dostarczonych metod)

Kod: Zaznacz cały

/*   main.c   */

#include "opak.h"

int main()
{
//   ...

   jakasMetoda(&opakObjOne);

//   ...

   jakasMetoda(&opakObjTwo);

//   ...

   return 0;
}


.

Re: Opaque Pointer czyli wskaźnik jakby opakowany.

: piątek 13 lip 2018, 10:13
autor: piotrek
Przydałby się jakiś mechanizm walidacji czy obiekt wskazywany jest tą właściwą strukturą, np jakaś suma kontrolna po bajtach pól albo kilka ifów dla każdego pola.

Re: Opaque Pointer czyli wskaźnik jakby opakowany.

: piątek 13 lip 2018, 11:37
autor: xor
No tak, takie coś oczywiście przejdzie kompilację:

Kod: Zaznacz cały

#include "opak.h"

struct Opak {
   int foo;
} Foo;

int main()
{
   jakasMetoda(&Foo);
   jakasMetoda(&opakObjOne);
   jakasMetoda(&opakObjTwo);

   return 0;
}

Re: Opaque Pointer czyli wskaźnik jakby opakowany.

: piątek 13 lip 2018, 11:48
autor: Antystatyczny
Przy bardzo wymagającym sofcie sprawdzam zakresy wartości pól w strukturze, której wskaźnik został mi przekazany, poza tym ostatnim polem struktury jest suma kontrolna wszystkich wcześniejszych bajtów struktury (na ogół robię zwyczajny xor na wszystkich bajtach po kolei)

Re: Opaque Pointer czyli wskaźnik jakby opakowany.

: niedziela 22 lip 2018, 00:08
autor: mokrowski
opak.h

Kod: Zaznacz cały

#ifndef OPAK_H_
#define OPAK_H_

/* To wystarczy do deklaracji funkcji */
struct Opak;

void jakasFunkcja(struct Opak * const);
struct Opak * get_opak1_ptr(void);
struct Opak * get_opak2_ptr(void);

#endif /* OPAK_H_ */


opak.c

Kod: Zaznacz cały

#include "opak.h"

/*
 * Struktura która będzie ukryta pod "opakowanym" wskaźnikiem
 * Wbew pozorom jest trochę zalet że bez typedf w C :)
 */
struct Opak {
        int ene;
        char due;
        char *like;
        long fake;
};

/*
 * Konkretne instancje obiektu Opak zaalokowane statycznie?
 * Tylko brakowało static.
 */
static struct Opak opakObjOne;
static struct Opak opakObjTwo;

struct Opak * get_opak1_ptr(void) {
        /* Jakaś nietrywialna inicjalizacja struktury... */
        return &opakObjOne;
}

struct Opak * get_opak2_ptr(void) {
        /* Jakaś nietrywialna inicjalizacja struktury... */
        return &opakObjTwo;
}

/*
 * Funkcja operująca na obiekcie Opak
 */
void jakasFunkcja(struct Opak * const opak)
{
        ;
}


main.c

Kod: Zaznacz cały

#include <cstdlib.h>
#include "opak.h"

int main(void)
{
        /* Nawet tak bezpośrednio. Wiedząc że dane są statyczne */
        jakasFunkcja(get_opak1_ptr());
        jakasFunkcja(get_opak2_ptr());

        return EXIT_SUCCESS;
}