2012-11-06 10 views
7
static char buf[8]; 
void foo(){ 
    const char* ptr = buf; 
    /* ... */ 
    char* q = (char*)ptr; 
} 

È possibile che questo frammento genererà "warning: cast discards ‘__attribute__((const))’ qualifier from pointer target type [-Wcast-qual]". Mi piace lo -Wcast-qual poiché può aiutarmi a scrivere accidentalmente in memoria a cui non dovrei scrivere.esplicita Ignora le avvertenze da -Wcast-qual: del cast si disfa ‘__attribute __ ((const))’ qualificatore dal tipo di destinazione puntatore

Ma ora voglio escludere const per una singola occorrenza (non per l'intero file o progetto). La memoria a cui punta è scrivibile (proprio come buf sopra). Preferisco non rilasciare const da ptr poiché è usato altrove e mantenere i puntatori (uno const e uno non-const) sembra un'idea peggiore.

+1

Perché non solo 'char * q = buf;'? –

+0

Immagino che questo sia poco chiaro dallo snippet, eseguo l'aritmetica su ptr prima del cast. – ext

+1

Potrebbe essere preferibile utilizzare un indice nel buff invece di manipolare i puntatori quindi e passare ad es. '& buff [i]' invece di un puntatore? –

risposta

4

In GCC 4.2 e successive, è possibile sopprimere l'avviso per una funzione utilizzando #pragma. Lo svantaggio è che devi sopprimere l'avvertimento attraverso l'intera funzione; non puoi usarlo solo per alcune linee di codice.

#pragma GCC diagnostic push // require GCC 4.6 
#pragma GCC diagnostic ignored "-Wcast-qual" 
void foo(){ 
    const char* ptr = buf; 
    /* ... */ 
    char* q = (char*)ptr; 
} 
#pragma GCC diagnostic pop // require GCC 4.6 

Il vantaggio è che l'intero progetto può utilizzare le stesse opzioni di avviso/controllo errori. E tu sai esattamente cosa fa il codice, e fai in modo che GCC ignori un controllo esplicito di un pezzo di codice.
Poiché la limitazione di questo pragma, è necessario estrarre il codice essenziale dalla funzione corrente a quella nuova e creare la nuova funzione da sola con questo #pragma.

+3

** Abilitato per avvertimenti predefiniti: La compilazione del compilatore GNU (GCC) 4.6.3 potrebbe generare abilitato da avvisi predefiniti che non possono essere soppressi. ** '-Wcast-qual' è uno di questi:' avviso: inizializzazione scarti 'const' qualificatore dal tipo di target puntatore ** [abilitato per impostazione predefinita] ** ' –

+0

@AlterMann: si tratta di un avviso completamente diverso che si verifica quando si effettua una ** conversione ** implicita che elimina il qualificatore' const' (che non è valido C; C non ha una conversione così implicita). Non è l'avviso che l'OP sta vedendo. L'avviso –

-1

po 'tardi, ma si può anche fare questo senza pasticciare con avvisi a tutti:

static char buf[8]; 
void foo(){ 
    const char* ptr = buf; 
    /* ... */ 
    char* q = buf + (ptr-buf); 
} 

Si finisce con q = buf + ptr - buf = ptr + buf - buf = ptr, ma con buf s' costanza.

(Sì, questo consente di rimuovere const da qualsiasi puntatore a tutti, const è di consulenza, non è un meccanismo di sicurezza.)

+0

è ancora presente utilizzando gcc 4.7.2 – malat

7
#include <stdint.h> 

const char * ptr = buf; 
.... 
char * p = (char *)(uintptr_t)ptr; 

Oppure, senza stdint.h:

char * p = (char *)(unsigned long)ptr; 
+0

Scorri questo approccio. Non aggirare gli avvertimenti. Se non li vuoi, usa le soppressioni, che è ciò a cui sono destinate. Ciò sarà esplicito sulle tue intenzioni e renderà il tuo codice molto più leggibile. –

+0

Le soppressioni non sono generalmente portatili. E se condividi il tuo codice, qualcuno compilerà qualcosa che odia il tuo metodo di soppressione. Se vuoi essere esplicito: #define UN_CONSTIFY (_t, _v) ((_t) (uintptr_t) (_ v)) –

Problemi correlati