2009-11-24 16 views
6

Lo siento si esto es simple, mi C++ está oxidado.código de C++ ligeramente extraño

¿Qué está haciendo? No hay asignación o llamada de función por lo que puedo ver. Este patrón de código se repite muchas veces en algún código que heredé. Si es importante, es código incrustado.

*(volatile UINT16 *)&someVar->something; 

editar: continuando desde allí, ¿confirma el siguiente código adicional Heaths suspicions? (Exactamente desde el código, incluyendo la repetición, a excepción de los nombres han sido cambiados para proteger a los inocentes)

if (!WaitForNotBusy(50)) 
    return ERROR_CODE_X; 

*(volatile UINT16 *)& someVar->something; 

if (!WaitForNotBusy(50)) 
    return ERROR_CODE_X; 

*(volatile UINT16 *)& someVar->something; 
x = SomeData; 
+1

¿Código incrustado? Entonces esta es probablemente una dirección física, como sospecha Sharth. –

+0

Nota: Agregué un enlace al artículo en la respuesta a continuación: http://www.mjmwired.net/kernel/Documentation/volatile-considered-harmful.txt – Artyom

+0

Es una buena idea lanzar el resultado de una lectura que no va a ninguna parte. con '(void)', para evitar advertencias del compilador. Entonces '(vacío) * (volatile uint16_t *) & someVar-> something'. Por supuesto, envuelva esto en una función macro o en línea, ¡no corte y pegue esto por todos lados! –

Respuesta

19

Esta es una expresión bastante común en la programación incrustada (aunque debe estar encapsulada en un conjunto de funciones o macros) donde se necesita acceder a un registro de dispositivo. En muchas arquitecturas, registros del dispositivo se asignan a una dirección de memoria y se accede como cualquier otra variable (aunque en una dirección fija - ya sea punteros pueden ser utilizados o el enlazador o una extensión de compilador pueden ayudar con la fijación de la dirección).Sin embargo, si el compilador de C no ve un efecto secundario a un acceso variable, puede optimizarlo, a menos que la variable (o el puntero utilizado para acceder a la variable) se marque como volátil.

Así que la expresión;

*(volatile UINT16 *)&someVar->something; 

emitirá un 16-bit de lectura en algún desplazamiento (proporcionado por el elemento de desplazamiento something estructura) de la dirección almacenada en el puntero someVar. Esta lectura ocurrirá y no puede ser optimizada por el compilador debido a la palabra clave volatile.

Tenga en cuenta que algunos registros de dispositivos realizan algunas funciones incluso si simplemente se leen, incluso si la lectura de datos no se utiliza de otro modo. Esto es bastante común con los registros de estado, donde una condición de error puede borrarse después de la lectura del registro que indica el estado de error en un bit en particular.

Esta es probablemente una de las razones más comunes para el uso de la palabra clave volatile.

+0

Gracias, marqué esta como respuesta porque creo que es la respuesta más clara y completa. –

9

creo que la intención del autor era que el compilador emite barreras de memoria en estos puntos. Al evaluar el resultado de expresión de volátil, la indicación para el compilador es que esta expresión no debe optimizarse, y debe 'instanciar' la semántica de acceso a una ubicación volátil (barreras de memoria, restricciones de optimizaciones) en cada línea donde ocurre este modismo

Este tipo de expresiones idiomáticas se podría "encapsular" en una macro de preprocesador (#define) en caso de que otra compilación tenga una forma diferente de causar el mismo efecto. Por ejemplo, un compilador con la capacidad de codificar directamente barreras de lectura o escritura de memoria podría usar el mecanismo integrado en lugar de este modismo. La implementación de este tipo de código dentro de una macro permite cambiar el método en toda su base de código.

EDIT: sharth usuario tiene un gran punto de que si este código se ejecuta en un entorno donde la dirección del puntero es un física en lugar de virtuales dirección (o una dirección virtual asignada a una dirección física específica), luego, realizar esta operación de lectura podría causar alguna acción en un dispositivo periférico.

+2

Además, una macro podría hacer que sea más obvio lo que está sucediendo ... (#define READ_MEMORY_BARRIER ...) – Aaron

+1

El primer paso debe ser evaluar si realmente crea una barrera de memoria. Esa parece ser la intención, pero las variables volátiles en muchas plataformas solo se ordenan con respecto a otras variables volátiles. Incluso si funciona para esta plataforma integrada, puede que no funcione para otra; Buscaría una solución mejor y más portátil para crear barreras. –

+1

No creo que tenga nada que ver con barreras de memoria, es una plataforma integrada, y probablemente asigna una variable a algunos IO. –

9

Así que aquí hay una posibilidad remota.

Si esa dirección apunta a una región de memoria asignada en un FPGA u otro dispositivo, entonces el dispositivo podría estar haciendo algo cuando lea esa dirección.

+0

¿Por qué una posibilidad remota? Creo que es una explicación perfectamente lógica. +1 –

+0

La pregunta original carecía de muchas de las aclaraciones que dejan en claro que esto está sucediendo en un sistema integrado, etc. –

-1

Generalmente, este es un código incorrecto.

En C y C++ volátil significa muy pocos y no proporciona una barrera de memoria implícita. Por lo que este código es simplemente UNESS bastante mal está escrito como

memory_barrier(); 
*(volatile UINT16 *)&someVar->something; 

Es sólo mala código.

Expenation:volatile no hace variable atómico!

Reed este artículo: http://www.mjmwired.net/kernel/Documentation/volatile-considered-harmful.txt

Esta es la razón por volatile casi nunca debería usarse en código apropiado.

+2

¡¿Eh ?! Qué significa eso? – Clifford

Cuestiones relacionadas