Opaque Pointer czyli wskaźnik jakby opakowany.

W tym miejscu zadajemy pytania na temat języka C, dzielimy się swoją wiedzą, udzielamy wsparcia, rozwiązujemy problemy programistyczne.
Awatar użytkownika
xor
User
User
Posty: 169
Rejestracja: poniedziałek 05 wrz 2016, 21:44

Opaque Pointer czyli wskaźnik jakby opakowany.

Postautor: xor » czwartek 12 lip 2018, 23:20

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;
}


.

Awatar użytkownika
piotrek
User
User
Posty: 155
Rejestracja: niedziela 05 lis 2017, 02:46

Re: Opaque Pointer czyli wskaźnik jakby opakowany.

Postautor: piotrek » piątek 13 lip 2018, 10:13

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.

Awatar użytkownika
xor
User
User
Posty: 169
Rejestracja: poniedziałek 05 wrz 2016, 21:44

Re: Opaque Pointer czyli wskaźnik jakby opakowany.

Postautor: xor » piątek 13 lip 2018, 11:37

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;
}

Awatar użytkownika
Antystatyczny
Geek
Geek
Posty: 1168
Rejestracja: czwartek 03 wrz 2015, 22:02

Re: Opaque Pointer czyli wskaźnik jakby opakowany.

Postautor: Antystatyczny » piątek 13 lip 2018, 11:48

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)
"The true sign of intelligence is not knowledge but imagination" Albert Einstein.

Awatar użytkownika
mokrowski
User
User
Posty: 190
Rejestracja: czwartek 08 paź 2015, 20:50
Lokalizacja: Tam gdzie Centymetro

Re: Opaque Pointer czyli wskaźnik jakby opakowany.

Postautor: mokrowski » niedziela 22 lip 2018, 00:08

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;
}
,,Myślenie nie jest łatwe, ale można się do niego przyzwyczaić" - Alan Alexander Milne: Kubuś Puchatek


Wróć do „Pisanie programów w C”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 2 gości