Qual è la differenza tra scrivere sull'indirizzo di memoria di un int dichiarato e scrivere direttamente su un * int?

0

Sto scrivendo un programma in cui fscanizzo un file e scrivo ripetutamente nello stesso indirizzo di memoria. Ho provato il seguente:

FILE *f = fopen(fname, "r");
int* num;
while(fscanf(f, "%d,", num) != EOF)
 {
    printf("%d\n", *num);
} 

che, quando lo eseguo, produce Bus Error 10, il che significa che sto cercando di scrivere su un indirizzo non autorizzato. Tuttavia, funziona come segue:

FILE *f = fopen(fname, "r");
int num;
while(fscanf(f, "%d,", &num) != EOF)
{
    printf("%d\n", num);
}  

Entrambi compili bene, come mi aspetterei. Quello che non capisco è il motivo per cui posso scrivere direttamente su un indirizzo di memoria ma non su un puntatore a quell'indirizzo. E se non sono uguali, perché lo compila?

    
posta user1367123 24.07.2016 - 06:36
fonte

2 risposte

3

Nel primo tentativo, "num" è un puntatore non inizializzato e fscanf (che si aspetta un puntatore) sta tentando di memorizzare un int attraverso quel puntatore. Ma "num" sta probabilmente puntando nella memoria protetta (probabilmente la posizione 0), dal momento che non è stata inizializzata per puntare ovunque.

Nel tuo secondo tentativo, "num" è un int, e la memoria è stata allocata per esso dalla sua definizione "int num;". Quindi, fscanf riceve un puntatore a quella posizione di memoria e memorizza correttamente l'int, poiché la posizione di memoria è valida (che non era al primo tentativo).

    
risposta data 24.07.2016 - 08:05
fonte
3

Both compile fine, as I'd expect.

Entrambi non si compongono bene. Ricevo gli avvisi del compilatore sul primo (quello sbagliato) da più compilatori se imposto il livello di avviso del compilatore su un valore ragionevole come -Wall con gcc e clang. Come regola generale, è meglio abilitare sempre un livello elevato di avvisi del compilatore e disabilitarli solo quando si utilizza una libreria di terze parti necessaria che non viene compilata in modo pulito per gli standard generando molti avvisi. (Odio quando succede.)

Un compilatore a metà strada decreterà che il puntatore non è stato inizializzato in questo caso . Il problema generale di determinare se a una variabile è stato assegnato un valore prima di accedere è equivalente alla risoluzione del problema di interruzione. L'accesso a una variabile non assegnata è considerato un comportamento indefinito piuttosto che un errore a causa di ciò.

    
risposta data 24.07.2016 - 20:31
fonte

Leggi altre domande sui tag