2012-01-31 6 views
13

Immaginate Ho questa funzione C (e il prototipo corrispondente in un file di intestazione)Comportamento non definito per escludere la costanza di un parametro di funzione?

void clearstring(const char *data) { 
    char *dst = (char *)data; 
    *dst = 0; 
} 

C'è comportamento non definito nel codice qui sopra, getto del const via, o è solo una pratica di programmazione terribilmente male ?

Supponiamo che non vi siano oggetti const qualificati usati

char name[] = "pmg"; 
clearstring(name); 
+2

Se il cast non è UB, penso che dovrebbe essere :) – pmg

+0

sicuramente hai il piede esattamente nel mirino del fucile! –

+1

@ pmg: se il cast stesso fosse UB, non ci sarebbe molto il linguaggio che lo consentiva - è abbastanza facile per un compilatore rilevare che 'const' è stato aggiunto in un cast, allo stesso modo in cui rileva che' char * dst = data; 'è illegale. Ovviamente ci sono alcune cose inutili che lo standard consente per ragioni storiche, ma io sostengo che questo non è uno di loro :-) –

risposta

20

Il tentativo di scrivere *dst è UB se il chiamante si passa un puntatore ad un oggetto const, o un puntatore a una stringa letterale.

Ma se il chiamante ti passa un puntatore a dati che di fatto sono mutabili, allora il comportamento è definito. La creazione di un const char* che punta a un char modificabile non rende immutabile tale char.

Quindi:

char c; 
clearstring(&c); // OK, sets c to 0 
char *p = malloc(100); 
if (p) { 
    clearstring(p); // OK, p now points to an empty string 
    free(p); 
} 
const char d = 0; 
clearstring(&d); // UB 
clearstring("foo"); // UB 

Cioè, è estremamente mal consigliato la vostra funzione, perché è così facile per un chiamante per causare UB. Ma è infatti possibile utilizzarlo con un comportamento definito.

+4

+1: (im) la mutabilità è una proprietà intrinseca dell'oggetto stesso, indipendentemente dalla qualifica del puntatore utilizzato per accedervi ... – Christoph

+0

Questo UB è dovuto a 'C99 6.6 §9' oa causa di' C99 6.7.3 §5'? – Lundin

+1

@Lundin: il secondo (e 6.4.5/6 piuttosto che 6.7.3/5 nel caso del letterale stringa, poiché i valori letterali stringa non sono oggetti 'const' in C). Le costanti dell'indirizzo non hanno nulla a che fare con questo. –

0

Si consideri una funzione come strstr che, se fornita un puntatore a una parte di un oggetto contenente una stringa, restituisce un puntatore a una parte eventualmente diversa dello stesso oggetto. Se il metodo passa un puntatore a un'area di memoria di sola lettura, restituirà un puntatore a un'area di memoria di sola lettura; allo stesso modo se viene assegnato un puntatore a un'area scrivibile, restituirà un puntatore a un'area scrivibile.

Non c'è modo in C per avere una funzione di restituire un const char * quando somministrato un const char *, e restituire una normale char * quando dato un normale char *. Per essere compatibile con il modo in cui strstr ha funzionato prima che l'idea di un const char * sia stata aggiunta alla lingua, è necessario convertire un puntatore qualificato const in un puntatore non abilitato alla costante. Anche se è vero che una funzione di libreria strstr potrebbe avere il diritto di eseguire tale cast anche se il codice utente non è in grado di farlo, lo stesso schema appare abbastanza spesso nel codice utente che sarebbe opportuno vietarlo.

Problemi correlati