c++ - software - volatile int
estructura volátil=struct no es posible, ¿por qué? (3)
struct FOO{
int a;
int b;
int c;
};
volatile struct FOO foo;
int main(void)
{
foo.a = 10;
foo.b = 10;
foo.c = 10;
struct FOO test = foo;
return 0;
}
Esto no compilará, porque struct FOO test = foo;
genera un error:
error: la referencia obligatoria del tipo ''const FOO &'' a ''volátil FOO'' descarta los calificadores
¿Cómo puedo copiar una volatile struct
en otra struct
en C ++ (antes de C ++ 11)?
Mucha gente sugirió simplemente eliminar volátiles, pero no puedo hacer eso en ese caso, porque quiero copiar los ajustes actuales de SPI-Reg dentro de un μC y los encabezados del fabricante lo declaran volátil. Quiero copiar esas configuraciones, porque el fabricante también proporciona una Biblioteca para usar el SPI para EnDat-Communication, y no tengo acceso al código fuente. Como tengo que cambiar las configuraciones SPI-Reg-Settings durante el tiempo de ejecución, quiero volver fácilmente a la configuración SPI de la biblioteca sin llamar de nuevo a init_endat () - lib fkt (no se especifica qué sucede si lo llamo dos veces).
¿Podría posiblemente usar memcopy () para eso?
Como se sugirió, esta es una copia de la siguiente pregunta.
¿Por qué no se me proporciona un constructor de copia predeterminado de un volátil?
Esto está mal formado porque FOO
tiene un constructor de copia implícito definido como:
FOO(FOO const&);
Y escribes FOO test = foo;
con foo
de tipo volatile FOO
, invocando:
FOO(volatile FOO const&);
Pero la conversión implícita de referencias a volátil a referencias a no volátiles está mal formada.
A partir de aquí, surgen dos soluciones:
- no haga volátil a las conversiones no volátiles;
- definir un constructor de copia adecuado o copiar los miembros del objeto "manualmente";
-
const_cast
puede eliminar el calificador volátil, pero este es un comportamiento indefinido para usarlo si su objeto subyacente es efectivamente volátil.
¿Podría posiblemente usar memcopy () para eso?
No, no puedes, memcpy
es incompatible con objetos volátiles: no hay una sobrecarga de él que tome punteros a volátiles, y no hay nada que puedas hacer sin invocar un comportamiento indefinido.
Entonces, como conclusión, su mejor opción si no puede agregar un constructor a FOO
es definir:
FOO FOO_copy(FOO volatile const& other)
{
FOO result;
result.a = other.a;
result.b = other.b;
result.c = other.c;
return result;
}
O con C ++ 11 std::tie
:
FOO FOO_copy(FOO volatile const& other)
{
FOO result;
std::tie(result.a, result.b, result.c) = std::tie(other.a, other.b, other.c);
return result;
}
No ha proporcionado suficientes detalles sobre su problema para realizar una evaluación más precisa, pero la solución al problema que está tratando de resolver es casi seguro que no se debe usar volatile
. "Volátil" significa que el valor puede cambiar debajo de sus pies: los dos típicos casos de buen uso son variables modificadas desde manejadores de señal UNIX y registros mapeados en memoria. Volátil no es suficiente para variables compartidas entre hilos, notablemente.
La razón por la que recibe este error es porque su compilador está tratando de encontrar un constructor de copia FOO(volatile FOO&)
, que nunca se genera automáticamente.
Para dar otro enfoque a una respuesta, para abordar por qué esto no tiene sentido, en lugar de simplemente donde el estándar de C ++ dice que esto no es válido:
El objetivo de todo lo volatile
es tener un control preciso sobre a qué variable se accede cuando. Eso significa que dado volatile int i, j;
, i = 1; j = 2;
i = 1; j = 2;
y j = 2; i = 1;
j = 2; i = 1;
no hagas lo mismo El compilador no puede transformar libremente uno en el otro. Lo mismo se aplica a las lecturas: dado volatile int i, j; int x, y;
volatile int i, j; int x, y;
, x = i; y = j;
x = i; y = j;
y y = j; x = i;
y = j; x = i;
no hagas lo mismo La presencia de volatile
significa que los accesos deben ocurrir exactamente en el orden que usted especificó.
Ahora, en tu ejemplo, ¿qué debería struct FOO test = foo;
¿hacer? Nunca ha especificado si primero quiere leer foo.a
, luego foo.b
, finalmente foo.c
, o quizás primero lea foo.c
, luego foo.b
, finalmente foo.a
, o tal vez algún otro orden.
Si lo desea, puede hacer esto:
struct FOO test;
test.a = foo.a;
test.b = foo.b;
test.c = foo.c;
Aquí, especifica explícitamente el orden de los accesos a los campos de foo
, para evitar el problema.