Un cast che sta rompendo le regole severe-aliasing
-
04-10-2019 - |
Domanda
Ho una funzione che richiede molto * ed esigenze senza segno di passare ad una libreria esterna che accetta un unsigned int * e su questa piattaforma int unsigned / lungo hanno la stessa dimensione.
void UpdateVar(unsigned long* var) {
// this function will change the value at the address of var
ExternalLibAtomicUpdateVar((unsigned int*)var); // lib atomically updates variable
}
Questo genera un avviso dicendo che la sua rottura regole severe-aliasing. Ci sono arounds di lavoro?
Grazie
Edit: mi scuso per non essere chiaro. Il codice è un aggiornamento atomica in modo da andare in giro per la libreria per memorizzare non è un'opzione. Potrei scendere fino a assemblaggio, ma mi piacerebbe fare questo in C ++.
Soluzione
void UpdateVar(unsigned long* var) {
unsigned int x = static_cast<unsigned int>(*var);
ExternalLibUpdateVar(&x);
*var = static_cast<unsigned long>(x);
}
Altri suggerimenti
Questo dovrebbe funzionare:
void UpdateVar(unsigned long* var) {
// this function will change the value at the address of var
ExternalLibUpdateVar(reinterpret_cast<unsigned int*>(var));
}
Niente nei mandati C standard che int
e long
devono avere le stesse dimensioni; inoltre, anche se hanno la stessa dimensione, nulla nei mandati standard che hanno la stessa rappresentazione (tra le altre cose, che potrebbero avere combinazioni incompatibili di bit di riempimento e rappresentazioni trappola, tale che aliasing tra i due tipi non può servire qualsiasi scopo utile).
Gli autori dello standard non ha voluto per forza esecutori mirati piattaforme dove aliasing tra int
e long
non servirebbe a nulla per riconoscere quali aliasing. Inoltre non hanno voglia di scrivere le regole che sarebbero applicabili ad alcune piattaforme (quelle in cui aliasing servirebbe uno scopo), ma non altri (quelli in cui non sarebbe). Al contrario, hanno pensato che le persone che scrivono i compilatori di qualità avrebbero cercato di riconoscere aliasing nei casi in cui era utile.
Essere in grado di utilizzare i puntatori a un tipo a 32-bit per leggere e scrivere i valori di un altro tipo a 32-bit che ha la stessa rappresentazione è chiaramente utile, soprattutto se le API sono divisa su quale tipo che si aspettano. Se alcune API banale su un int*
uso della piattaforma per i valori a 32 bit e altri usano long*
, un qualità implementazione general-purpose per quella piattaforma deve consentire i dati di entrambi i tipi a cui accedere utilizzando i puntatori dell'altra.
Purtroppo, però, di alcuni compilatori gli autori sono più interessati a elaborazione di un certo sottoinsieme di programmi in fretta, che in elaborazione di un più ampio sottogruppo di programmi utilmente, e non possono essere invocate per generare il codice utile se è necessario lo scambio di dati tra API che utilizzano la stessa rappresentazione dei dati, ma diversi tipi di nome a meno che uno disabilita completamente aliasing analisi. Naturalmente, se uno si rivolge dialetti di C che sono adatti per l'uso generico su microcontrollori, tali questioni non contano.