Bien ... En C, es muy útil para cualquier lugar donde necesite código para describir una estructura de datos. Lo he usado, p. para hacer la GUI generada en tiempo de ejecución para las opciones de configuración.
Esto funcionaba así: un comando que necesita opciones define una estructura local que contiene sus opciones, y luego describe esa estructura para el código que genera la GUI, usando offsetof
para indicar dónde están los campos. El uso de compensaciones en lugar de direcciones absolutas permite que el código de la GUI funcione con cualquier instancia de la estructura, no solo una.
Esto es un poco difícil de esbozar rápidamente en un ejemplo (lo intenté), pero como los comentarios indican que hay un ejemplo en orden, lo intentaré de nuevo.
Supongamos que tenemos un módulo autónomo, llamado "comando", que implementa alguna acción en la aplicación. Este comando tiene un conjunto de opciones que controlan su comportamiento general, que debe exponerse al usuario a través de una interfaz gráfica de usuario. A los fines de este ejemplo, supongamos que la aplicación es un administrador de archivos, y el comando podría ser, p. "Dupdo".
La idea es que el código de copia viva en un archivo C y el código GUI en otro, y que el código GUI no necesite estar codificado para "admitir" las opciones del comando de copia. En su lugar, definimos las opciones en el archivo de copia, así:
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. */
A continuación, el comando de copia registra sus valores de configuración con el módulo de interfaz gráfica de usuario:
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);
}
Entonces, digamos que el usuario pide a establece las opciones del comando de copia. entonces podemos copiar primero las opciones actuales, para apoyar la cancelación, y pedir al módulo de interfaz gráfica de usuario para un cuadro de diálogo controles de retención, construido en tiempo de ejecución, adecuada para la edición de las opciones de este comando:
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;
}
}
Por supuesto, este código se supone las configuraciones son tipos de valores puros, por lo que podemos copiar la estructura mediante una simple asignación de estructuras. Si también admitimos cadenas dinámicas, necesitaríamos una función para hacer la copia. Sin embargo, para los datos de configuración, cualquier cadena probablemente se exprese mejor como una matriz de tamaño estático char
en la estructura, lo cual estaría bien.
Nota cómo el hecho de que el módulo de interfaz gráfica de usuario sólo se sabe dónde vive cada valor expresados como un desplazamiento nos permite proporcionar la función de diálogo con una copia temporal en la pila. Si en cambio hubiéramos configurado el módulo GUI con punteros directos para cada campo, esto no sería posible, lo que sería mucho menos flexible.
Su primer uso es legítimo en C, pero en C++ punteros a miembro bastante eliminar tanto la necesidad. –
Aquí es alguna otra pregunta sobre ella: http://stackoverflow.com/questions/400116/what-is-the-purpose-and-return-type-of-the-builtinoffsetof-operator –