Durante la scrittura di un codice C, mi sono imbattuto in un piccolo problema in cui dovevo convertire un carattere in una "stringa" (un po 'di memoria il cui inizio è dato da un puntatore char*
).Questo comportamento del cast (char *) & x è ben definito?
L'idea è che se qualche sourcestr
puntatore viene (non NULL
), quindi dovrei usarlo come il mio "stringa finale", altrimenti dovrei convertire un dato charcode
nel primo personaggio di un altro array, e utilizzarlo al posto .
Ai fini di questa domanda, assumeremo che i tipi di variabili non possano essere modificati in anticipo. In altre parole, non posso semplicemente memorizzare il mio charcode
come const char*
anziché int
.
Poiché tendo ad essere pigro, ho pensato tra me e me: "hey, non potrei semplicemente usare l'indirizzo del personaggio e trattare quel puntatore come una stringa?". Ecco un piccolo frammento di quello che ho scritto (non fracassare la testa contro il muro appena ancora!):
int charcode = FOO; /* Assume this is always valid ASCII. */
char* sourcestr = "BAR"; /* Case #1 */
char* sourcestr = NULL; /* Case #2 */
char* finalstr = sourcestr ? sourcestr : (char*)&charcode;
Ora, naturalmente, ho provato, e come mi aspettavo, funziona. Anche con alcuni flag di avviso, il compilatore è ancora felice. Tuttavia, ho questa strana sensazione che questo è in realtà un comportamento indefinito, e che non dovrei farlo.
Il motivo per cui penso in questo modo è perché gli array char*
devono essere terminati con null per essere stampati correttamente come stringhe (e io voglio che sia il mio!). Tuttavia, non ho la certezza che il valore a &charcode + 1
sarà zero, quindi potrei finire con qualche follia di overflow del buffer.
C'è un motivo reale per cui funziona correttamente oppure sono stato solo fortunato a ottenere gli zeri nei punti giusti quando ho provato?
(Si noti che non sto cercando altri modi per ottenere la conversione. Potrei semplicemente utilizzare una variabile char tmp[2] = {0}
, e mettere il mio carattere in corrispondenza dell'indice 0. Potrei anche usare qualcosa come sprintf
o snprintf
, a condizione che 'm abbastanza attenti con buffer overflow C'è una miriade di modi per farlo, io sono solo interessato al comportamento di questa particolare operazione getto)
Edit:.. ho visto alcune persone chiamano questo Hackery, e siamo chiari: sono completamente d'accordo con te. Non sono abbastanza un masochista per farlo nel codice rilasciato. Questo è solo io che mi incuriosisce;)
Nel caso 2, se si stampa quel puntatore come stringa, allora no, non è definito. – 2501
'char *' è un puntatore. C non ha un tipo di stringa. L'avviso del compilatore esiste per buone ragioni. Prestare attenzione a loro. – Olaf
In sé e per sé non è UB, tuttavia quando lo tratti come una stringa (come stampandola con printf o simili) diventa UB – Magisch