2016-04-13 18 views
10

strstr è una funzione C99 conforme, la firma di tipo, che è la seguente:Come implementare strstr() senza eseguire il commit di const?

char *strstr(const char *haystack, const char *needle); 

E 'possibile implementare questa funzione senza gettando via un const da qualche parte?

Per riferimento, qui è Apple's implementation e qui è GNU's implementation. Entrambi eliminano lo const alla fine.

+0

Non è necessario modificare nulla (?) – sircodesalot

+2

@sircodesalot In che modo si * scrive * la funzione senza gettare via 'const' per restituire un puntatore? – Ana

+0

Sono d'accordo con te. Il tipo di ritorno dovrebbe essere 'const char *'. – user3386109

risposta

9

Non è possibile implementare strstr() senza violare la correttezza const in qualche modo. Un cast è il modo più semplice per farlo. Probabilmente puoi nascondere la violazione in qualche modo (ad esempio potresti usare memcpy() per copiare il valore del puntatore), ma non ha senso farlo.

Il problema è che strstr() prende un const char* che punta a una stringa, e restituisce un non constchar* che punta nella stessa stringa.

Ad esempio, questo programma:

#include <stdio.h> 
#include <string.h> 
int main(void) { 
    const char s[] = "hello"; 
    char *result = strstr(s, "hello"); 
    *result = 'H'; 
    puts(result); 
} 

modifica (o almeno tentativi di modificare) un oggetto Qualificato const, senza utilizzare un getto puntatore o qualsiasi altro costrutto ovviamente non sicura.

Nel 1989, il comitato ANSI C potrebbe potuto evitare questo problema, definendo due funzioni diverse, dire:

const char *strcstr(const char *haystack, const char *needle); 
     char *strstr (  char *haystack, const char *needle); 

uno che restituisce un puntatore ad un const char dato un const argomenti, e un altro che restituisce il puntatore a un modificabile char dato un argomento modificabile. (C++, che eredita la libreria standard C, lo fa sovraccaricando.)

strstr() è una delle numerose funzioni di stringa standard che presentano questo problema.

+0

Il problema di base è che 'strstr' precede il concetto di' const' nel linguaggio C ... –

+0

@Chris Dodd: Anche se così non fosse, direi che l'interfaccia corrente sarebbe ancora più appropriata in C rispetto a quanto sopra con due funzioni. – AnT

+0

@AnT: In che modo un'interfaccia che ti consente di violare in silenzio la correttezza di 'const' più appropriata? –

0

Quello che state vedendo in caso di strstr (e alcune altre funzioni standard) è una soluzione idiomatica, il cui intento è quello di supportare le operazioni non modifica su entrambi i const e non const corde con una singola funzione .

Sì, per implementare tale funzione è necessario eliminare esplicitamente la costanza dal puntatore di input. Si noti che il cast da solo non viola ancora fisicamente nulla (nel senso che non tenta di modificare i dati costanti e non causa un comportamento indefinito). Tuttavia, apre la porta a tali violazioni restituendo un puntatore non-const ai dati const al chiamante, cioè viola le regole concettuali di cost-correctness.

Una soluzione alternativa sarebbe quella di fornire due versioni della stessa funzione standard, una const e una non const, ma senza la funzione di stile C++, questo richiederebbe due nomi di funzioni distinti, che non necessariamente assomigliano una buona idea (e anche con lo stile in C++, l'overloading ha anche i suoi problemi).

In questo caso è effettivamente responsabilità del chiamante ricevere il risultato in un puntatore dello stesso tipo di quello passato come argomento.Se il puntatore dell'argomento era const-qualificato, è un'ottima pratica di programmazione ricevere il risultato in un puntatore che è anche const-qualificato. Finché questa linea guida viene osservata, questo idioma si sente davvero a suo agio nel regno del linguaggio C.

+0

C++ richiede infatti sovraccaricamenti const per strstr e amici, vedi sez. 21.8. Che problemi vedi con questo? – rici