2016-02-20 9 views
8

Volevo trasferire elementi da una stringa a un'altra stringa, quindi ho scritto il seguente programma. Inizialmente, pensavo che il ciclo for dovrebbe essere eseguito fino a quando il carattere NULL (incluso quello che è stato) è stato copiato. Ma in questo codice, il ciclo for termina se è stato trovato un carattere NULL (cioè non ancora copiato), ma è ancora in grado di visualizzare la stringa in cui sono stati copiati gli elementi. Com'è possibile, se non c'è un carattere NULL in primo luogo?Copia di elementi da un array di caratteri a un altro

#include<stdio.h> 
#include<stdlib.h> 

int main() 
{ 
    char temp[100], str[100]; 
    fgets(str, 100, stdin); 
    int i; 
    for(i = 0; str[i]!='\0'; i++) 
    { 
     temp[i] = str[i]; 
    } 
    puts(temp); 
    return 0; 
} 
+3

'NULL' è una macro con una costante del puntatore _null_. Questo è irrilevante qui. Intendi il carattere ASCII 'NUL' o' nul' con il valore intero '0'. – Olaf

+0

Ulteriori informazioni su 'strcpy'. –

+1

@Pete Becker Penso che questo sia MOLTO probabile che sia qualcosa di simile a un problema di compiti a casa/tutorial (* cioè * destinato/progettato per rendere ** un ** consapevole dei problemi con le stringhe di copia). Dire semplicemente a qualcuno di leggere di 'strcpy' non aiuta a realizzare quella comprensione. – Tersosauros

risposta

7

La funzione void puts(const char *) deduce size_t strlen(const char *) e l'uscita di questa funzione è undefined quando non c'è terminatore nullo nel argomento passato (vedi this answer). Quindi nel tuo caso lo strlen all'interno di puts probabilmente ha trovato un valore 0 "accanto" alla tua matrice in memoria risultante in un comportamento corretto di puts, tuttavia non è necessario che sia sempre il caso in quanto non è definito.

3

Quando si dichiara char temp[100] senza inizializzarlo su qualcosa, è sufficiente una memoria non inizializzata. Questo ricordo può essere qualsiasi cosa. Ad esempio, il seguente programma scriverà il contenuto iniziale di che, come numeri interi:

#include<stdio.h> 
#include<stdlib.h> 

int main() 
{ 
    char temp[100]; 
    int i; 
    for(i = 0; i < 100 ; i++) 
    { 
     fprintf(stdout, "%d ", temp[i]); 
    } 
    return 0; 
} 

Questo stampa uscita costantemente diverso per me, anche se da qualche colpo di fortuna mantiene sezioni di stampa di zeri. ad esempio:

88 -70 43 81 -1 127 0 0 88 -70 43 81 -1 127 0 0 1 0 0 0 0 0 0 0 112 -70 43 81 -1 127 0 0 0 64 -108 14 1 0 0 0 72 50 -13 110 -1 127 0 0 -128 -70 43 81 -1 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 96 -70 43 81

88 90 72 88 -1 127 0 0 88 90 72 88 -1 127 0 0 1 0 0 0 0 0 0 0 112 90 72 88 -1 127 0 0 0 -96 119 7 1 0 0 0 72 18 72 105 -1 127 0 0 -128 90 72 88 -1 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 96 90 72 88

88 -6 -79 87 -1 127 0 0 88 -6 -79 87 -1 127 0 0 1 0 0 0 0 0 0 0 112 -6 -79 87 -1 127 0 0 0 0 14 8 1 0 0 0 72 34 57 104 -1 127 0 0 -128 -6 -79 87 -1 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 96 -6 -79 87

ciò che è più probabile accadendo è che la stringa non null-terminata è essere accidentalmente terminazione null in virtù del fatto che temp[strlen(str)] è , da un colpo di fortuna, \0.

+1

stampando queste variabili non è un comportamento indefinito –

+0

@Giorgi In che modo? AFAIK, è definito che ottengo 100 byte, ma i valori di quei byte non sono definiti. Dovrebbero essere sicuri da stampare, ma non è mai garantito quello che sono. – yaakov

+2

No, per favore leggi la nozione di comportamento non definito. La lettura delle variabili non inizializzate è UB. –

7

Ecco l'input e l'output sul mio computer:

0 
0 
絯忐` 

Process returned 0 (0x0) execution time : 1.863 s 
Press any key to continue. 

Vedere la spazzatura "絯 忐`"? Questo è un comportamento indefinito. Il tuo programma funziona bene perché sei (non fortunato).

Ancora, i comportamenti non definiti non meritano la discussione molto.

+3

Avevo intenzione di fare +1, fino a quando ho letto l'ultima riga: ** "** _ i comportamenti non definiti non meritano una discussione ._ **" ** Mentre è vero, l'OP era "(dis) fortunato" come Mettilo, penso che non riuscire a discutere di questo ** comportamento non definito ** è * non riuscire a rispondere correttamente alla domanda *. – Tersosauros

+1

Tutto e tutto possono accadere quando si verificano comportamenti indefiniti. Come fa notare saggiamente K & R, "se non sai come sono fatti su varie macchine, quell'innocenza potrebbe aiutarti a proteggerti." Quindi penso che sia meglio non discutere di comportamenti indefiniti. –

Problemi correlati