E 'impossibile scrivere callback corretti, const corretti in C?

2

In C, un oggetto non const converte implicitamente, senza preavviso, nella sua controparte const, quindi puoi scrivere una funzione e chiamarla come:

void foo( const char *p );
char bar[] = "bar";
foo( bar );

Tuttavia, se la funzione deve essere chiamata tramite un puntatore, sembra che tu non possa essere costante senza ricevere un avviso:

void foo( void (*callback)(char *p) );
void bar( const char *p );
foo( bar );

la barra non ha bisogno di modificare la stringa puntata a, e quindi per correttezza const corretta, dovrebbe essere dichiarata con const, ma passandola come un callback a una funzione che è disposta a dare l'accesso in scrittura callback, genera un avvertimento che i puntatori non sono compatibili.

Questa è una svista / difetto nello standard C?

    
posta psusi 21.04.2016 - 03:55
fonte

1 risposta

2

Il fatto che tu possa utilizzare un wrapper per evitare l'avviso dovrebbe mostrare che non esiste un motivo tecnico approfondito:

void bar(const char *p) { /* ... */ }
void bar_w(char *p) { bar(p); }  /* wrapper */

foo(bar_w);  /* instead of foo(bar) */

Questo è basato sul fatto allora ben noto che puoi usare un pointer-to-T (per qualsiasi tipo T) dove un pointer-to-const-T è previsto (come nel tuo primo esempio).

L'avviso è dovuto a §6.7.5.3.15 - Dichiaratori di funzioni (da ISO / IEC 9899: TC3):

For two function types to be compatible...

[cut]

Moreover, the parameter type lists, if both are present, shall agree in the number of parameters and in use of the ellipsis terminator; corresponding parameters shall have compatible types.

e const char *p non è compatibile con char *p .

Ad ogni modo il compilatore emette solo un avvertimento (non un errore): forse il programmatore sta usando la funzione sbagliata (con una firma simile) e l'avvertimento può aiutare a identificare la situazione.

Se tutto è a posto, una funzione di cast esplicito / wrapper può risolvere rapidamente la "seccatura".

Modifica

it appears that char *p is compatible with const char *p, just not the other way around

char *p può essere convertito implicitamente in const char *p (§6.3.2.3):

For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type; the values stored in the original and converted pointers shall compare equal

(in altre parole, è possibile aggiungere const , volatile e restrict qualificatori. Il puntatore originale e il confronto risultano uguali.Vedi anche conversioni implicite ).

per es.

char n;
const char *p = &n;  /*   &n has type char *   */

Questo non significa che const char * (un puntatore al char qualificato const) sia compatibile con char * (puntatore al char):

For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types

(§6.7.5.1)

I puntatori sono identificati in modo identico (non sono qualificati!) ma non puntano a tipi compatibili ( const char non è compatibile con char ).

    
risposta data 21.04.2016 - 12:59
fonte

Leggi altre domande sui tag