Cóż ... W języku C jest to bardzo przydatne w każdym miejscu, w którym potrzebny jest kod do opisu struktury danych. Użyłem go np. do generowania graficznego GUI: s do ustawiania opcji.
To działało w następujący sposób: polecenie wymagające opcji definiuje lokalną strukturę z opcjami, a następnie opisuje tę strukturę do kodu, który generuje GUI, przy użyciu offsetof
do wskazania, gdzie znajdują się pola. Używanie odsunięć zamiast adresów bezwzględnych pozwala kodowi GUI pracować z każdym wystąpieniem struktury, a nie tylko jednym.
To jest trochę trudne do szybkiego szkicowania w przykładzie (próbowałem), ale ponieważ komentarze wskazują, że przykład jest w porządku, spróbuję jeszcze raz.
Załóżmy, że mamy samodzielny moduł, zwany "poleceniem", który implementuje pewne działanie w aplikacji. To polecenie ma wiele opcji, które kontrolują jego ogólne zachowanie, które powinno być widoczne dla użytkownika za pośrednictwem graficznego interfejsu użytkownika. Na potrzeby tego przykładu załóżmy, że aplikacja jest menedżerem plików, a komendą może być np. "Kopiuj".
Chodzi o to, że kod kopiowania znajduje się w jednym pliku C, a kod GUI w innym, a kod GUI nie musi być zakodowany na sztywno, aby "obsługiwać" opcje polecenia kopiowania. Zamiast tego, możemy zdefiniować opcje w pliku kopii, tak jak poniżej:
struct copy_options
{
unsigned int buffer_size; /* Number of bytes to read/write at a time. */
unsigned int copy_attributes; /* Attempt to copy attributes. */
/* more, omitted */
};
static struct copy_options options; /* Actual instance holding current values. */
Następnie polecenie copy rejestruje swoje ustawienia konfiguracji z modułem graficznym:
void copy_register_options(GUIModule *gui)
{
gui_command_begin(gui, "Copy");
gui_command_add_unsigned_int(gui, "Buffer size", offsetof(struct copy_options, buffer_size));
gui_command_add_boolean(gui, "Copy attributes", offsetof(struct copy_options, copy_attributes));
gui_command_end(gui);
}
Następnie, powiedzmy użytkownik prosi o ustaw opcje polecenia kopiowania. Możemy wtedy najpierw skopiować bieżące opcje, aby wspierać anulowanie i poprosić moduł GUI dla dialogowych kontroli gospodarstwa, zbudowany w czasie wykonywania, nadaje się do edycji opcji tej komendy to:
void copy_configure(GUIModule *gui)
{
struct copy_options edit = options;
/* Assume this opens a modal dialog, showing proper controls for editing the
* named command's options, at the address provided. The function returns 1
* if the user clicked "OK", 0 if the operation was cancelled.
*/
if(gui_config_dialog(gui, "Copy", &edit))
{
/* GUI module changed values in here, make edit results new current. */
options = edit;
}
}
oczywiście ten kod zakłada ustawienia mają być czystymi typami wartości, więc możemy skopiować strukturę za pomocą prostego przypisania struktury. Jeśli obsługiwaliśmy również ciągi dynamiczne, potrzebowalibyśmy funkcji do kopiowania. Jednak w przypadku danych konfiguracyjnych każdy ciąg najprawdopodobniej byłby najlepiej wyrażony w postaci statycznej wielkości tablicy char
w strukturze, co byłoby w porządku.
Uwaga, jak fakt, że tylko moduł GUI wie, gdzie każda wartość życia wyrażone jako offset pozwala nam zapewnić funkcję dialogowego z tymczasowej kopii na stosu. Gdybyśmy zamiast tego skonfigurowali moduł GUI z bezpośrednimi wskaźnikami dla każdego pola, nie byłoby to możliwe, co byłoby znacznie mniej elastyczne.
Twoje pierwsze użycie jest uzasadnione w C, ale w C++ wskaźniki-to-członka dość dużo usunąć potrzebę. –
Oto niektóre inne pytanie o tym: http://stackoverflow.com/questions/400116/what-is-the-purpose-and-return-type-of-the-builtinoffsetof-operator –