2015-04-23 13 views
25

La funzione standard strstr viene utilizzata per trovare la posizione di una sottostringa in una stringa. Entrambi gli argomenti della funzione sono di tipo const char *, ma il tipo restituito è char *.Come il ritorno di stringa non è una costante

Mi piacerebbe sapere come viene implementata una funzione standard che viola la cost-correttezza.

+5

Hai compreso cstring e non string.h? Altrimenti, stai usando le versioni C - dio sa quello che fanno. La versione di '' std :: strstr' di C++ restituisce solo 'char *' se il primo parametro è anche un 'non' '' '' 'char ''. Vedi [qui] (http://en.cppreference.com/w/cpp/string/byte/strstr). (Scusa, ho appena notato anche il tag C ... quale lingua stai effettivamente utilizzando?) –

+3

@TonyD La versione C è 'char * strstr (const char *, const char *); ' –

+3

Nota che in C++ ci sono [due overload di strstr] (http://www.cplusplus.com/reference/cstring/strstr/) uno con parametro char const * e uno con char normale *, e i valori di ritorno Seguire. –

risposta

13

C permette punta a memoria con const o non-const puntatori, indipendentemente se l'oggetto è stato definito con il qualificatore const o meno.

6.5 Espressioni

  1. Un oggetto ha la propria valore memorizzato accessibile solo da un'espressione lvalue che ha una delle dei seguenti tipi:

- una versione qualificato di un tipo compatibile con il tipo effettivo dell'oggetto,

il prototipo di strstr in C è:

char *strstr(const char *s1, const char *s2); 

Il puntatore restituito, se valido, punta alla stringa s1. Questo può essere ottenuto con un cast:

const char safe = 's' ; 
char* careful = (char*)&safe ; 

Il problema è modificare quella memoria.

6.7.3 Tipo qualificatori

  1. Se si tenta di modificare un oggetto definito con un tipo const qualificato attraverso l'uso di un Ivalue non-const -qualificato il tipo, il comportamento non è definito.

Dal momento che si è creato la stringa, si dovrebbe sapere se è possibile modificarlo o no, quindi è possibile accettare il valore di ritorno con un puntatore a const, per evitare problemi:

const char* find = strstr(...) ; 
28

Tutto il const char * sta dicendo che strstr non ha intenzione di modificare la stringa passata in esso.

Se si modifica la stringa restituita o meno dipende da voi in quanto è la vostra stringa!

In C++ questo è stato modificato sovraccaricando il metodo e avendo due versioni, la versione di input const ha un output const.

In C non ha abbastanza quel livello di sicurezza integrato per te e si presuppone che tu sappia se dovresti modificare la stringa restituita.

+3

Ciò che C non ha è in realtà un sovraccarico di funzione. Se la funzione è stata introdotta per la prima volta in C++, potrebbe venire in due versioni, const e non-const. Ma la funzione è stata introdotta per la prima volta in C. Inoltre, è stata introdotta nei tempi di K & R, quando non esisteva la parola chiave 'const'. – ach

13

Secondo ISO C++ 21,8 (7) strstr restituisce una const char* o un char* a seconda se si ottiene un const char* o un char*.

const char* strstr(const char* s1, const char* s2); 

char* strstr(char* s1, const char* s2); 
+3

Questo vale per C++, ma nello standard C99 'strstr' restituisce' char * '. – Paul

+2

Ho visto prima il tag C++, quindi ho usato lo standard C++. Hai ragione riguardo allo standard C. – NathanOliver

1

Il valore di ritorno non è la variabile che è stata passata alla funzione come parametro. Questa funzione restituisce un puntatore alla prima occorrenza nel pagliaio di una qualsiasi dell'intera sequenza di caratteri specificata nell'ago o un puntatore nullo se la sequenza non è presente nel pagliaio.

+1

È ancora correlato ad esso (essendo parte della stessa dichiarazione di matrice o allocazione di memoria), e quindi quasi sicuramente ha la stessa "corretta costanza" di pagliaio, se la funzione viene utilizzata correttamente. – Random832

5

Si esegue specificando la firma e lasciando l'implementazione ai builder del compilatore.

Nota che restituire un char* che punta a una stringa const char[] è pericoloso, ma non è ancora una violazione di alcuna regola. Tuttavia, qualsiasi tentativo di scrivere su quella memoria è ancora un comportamento indefinito.

2

C++ provides two versions uno che accetta gli argomenti const e quelli che accettano non-const.

const char* strstr(const char* str, const char* target);  
char* strstr(  char* str, const char* target); 

Dato che in C non possiamo sovraccaricare, ci ritroviamo con due scelte spiacevoli:

  • O prendiamo gli argomenti come non-const, ma se le nostre fonti sono infatti const allora abbiamo bisogno di eseguire un cast sgradevole a non-const.
  • La seconda opzione è quella che abbiamo, che prendiamo gli argomenti come const, ma restituiamo un non-const. Potremmo restituire un const char * ma non potremmo mai modificare il risultato.
4

La funzione strstr risale a un'era prima che esistesse un puntatore const. Nei casi in cui sarebbe stato legale per il codice scrivere nella memoria identificata dal primo puntatore passato a strstr, sarebbe legale per il codice scrivere nella memoria identificata dal puntatore restituito e nei casi in cui il valore restituito sarebbe utilizzato solo in modi che erano legali con un puntatore alla memoria di sola lettura (ad es. un letterale stringa), si poteva legalmente passare tale puntatore a strstr.

Se una funzionalità simile a strstr veniva definita oggi, potrebbe essere implementata utilizzando due metodi, uno dei quali potrebbe accettare qualsiasi puntatore e restituire un puntatore che non può essere scritto dal destinatario e uno solo accetta i puntatori scrivibili ma restituirebbe un puntatore che il destinatario potrebbe utilizzare come meglio crede. Poiché alcuni codici che utilizzavano strstr avrebbero dovuto passare i puntatori di sola lettura, tuttavia, e poiché alcuni codici che utilizzavano strstr dovevano essere in grado di scrivere nei puntatori che avrebbe prodotto quando venivano forniti puntatori scrivibili, era necessario disporre di un set di le qualifiche puntatore funzionano in entrambe le direzioni. La conseguenza è un insieme di qualifiche puntatore che non sono realmente "sicure" [poiché potrebbe restituire un puntatore scrivibile a un'area di memoria di sola lettura] e che consentono di compilare il codice in alcuni casi in cui "davvero non dovrebbe", ma che consentirà al codice scritto prima dei giorni dei puntatori const di continuare a funzionare come previsto.

Problemi correlati