Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 19
  1. #1

    [C] Stringe: char* e/o vettori

    Salve a tutti.

    Come da titolo, vorrei sapere la differenza nell'usare le stringhe nelle due forme consentite dal linguaggio C.

    Nello specifico, invece, vorrei presentare un problema in cui mi sono appena imbattuto.
    Ho scritto del codice totalmente "inutile" (giusto per curiosità e "divertimento"), e vi post il mio problema.

    La prima versione, quella problematica, era la seguente:
    codice:
    int main(int argc, char **argv) {
    	char *stringa = "Bla0 Bla1 Bla2 Bla3";
    	char *temp;
    	temp = strtok(stringa, " ");
    }
    strtok segnala un accesso illegale alla memoria, dovuto ovviamente da stringa.

    Se invece modifico, utilizzando la seguente versione
    codice:
    int main(int argc, char **argv) {
    	char stringa[128] = "Bla0 Bla1 Bla2 Bla3";
    	char *temp;
    	temp = strtok(stringa, " ");
    }
    funziona tutto bene.

    Perchè? Se le due notazioni per indicare una stringa sono equivalenti, ed entrambe sono inizializzate nello stesso modo (e questo vuol dire che anche nel primo caso la memoria per contenere la stringa viene allocata), perchè il primo caso mi dà un accesso illegale in memoria?

  2. #2
    Utente di HTML.it
    Registrato dal
    Dec 2006
    Messaggi
    156
    le stringhe sono memorizzate in modo diverso:
    - nel secondo caso, hai 128 byte nello stack della funzione main.
    - nel primo caso, nello stack di main, hai 4-8byte del puntatore a carattere, mentre il contenuto (costante) viene memorizzato in un'altra area di memoria a cui non puoi accedere in scrittura.

  3. #3
    Aggiungo che quando assegni uno string literal (ovvero, una stringa tra virgolette) ad un puntatore, il puntatore in questione non dovrebbe essere un char *, ma un const char *, in modo che il compilatore ti segnali se cerchi di modificarlo.
    In effetti il tipo degli string literal è const char *, ma la conversione a char * all'assegnamento è consentita per compatibilità con codice scritto quando ancora il C non aveva il const.
    Amaro C++, il gusto pieno dell'undefined behavior.

  4. #4
    Ringrazio per le risposte.

    Per chiarirmi le idee, approfitto fornendo un altro esempio "terra terra".

    codice:
    int main(int argc, char **argv) {
    	char *stringa;
    	stringa = malloc(128);
    	scanf("%s", stringa);
    	printf("%s", stringa);
    }
    Anche in questo caso ho "solo" un puntatore, eppure posso accedere in scrittura a quell'area di memoria. E' dovuto al fatto che l'allocazione dinamica con malloc è nello spazio di indirizzi di questo processo?

    Ma allora la stringa costante dei primi esempi in quale area è allocata che non posso accedervi in scrittura?

  5. #5
    una stringa const literal è allocata nello stack del main
    una stringa allocata con malloc si trova nell'heap che è proprio di tutto il processo

    ad ogni modo quando usi la malloc usala sempre nella forma classica e non così come hai fatto, ovvero:

    puntatore = (tipo*) malloc(numero*sizeof(tipo));
    all that you need:
    http://www.cplusplus.com/reference/clibrary/

  6. #6
    Grazie!
    Originariamente inviato da Celebron
    una stringa const literal è allocata nello stack del main
    Scusami se mi permetto, ma nel momento in cui dichiaro una stringa letterale, nello stack del main dovrebbe esserci solo il puntatore al primo carattere della stessa, mentre la stringa viene scritta in un'altra area della memoria.
    Sbaglio?

  7. #7
    Utente di HTML.it
    Registrato dal
    Dec 2006
    Messaggi
    156
    Non sbagli, generalmente, una stringa const literal NON è allocata nello stack.

  8. #8
    Utente di HTML.it L'avatar di Freax
    Registrato dal
    Jul 2006
    Messaggi
    460
    giusto per confonderti un altro po' le idee ti dico che in C gli array di fatto non esistono come si potrebbe credere, anche gli array sono puntatori, infatti gli array rispondono allo stesso modo dei puntatori all'aritmetica dei puntatori, in pratica con gli array si sottointende l'uso di un puntatore, un array non è altro che un puntatore che semplifica la gestione della memoria al programmatore.

    EDIT: questo è quello che intendo

    codice:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(){
        int mioVettore[5]={56,87,123,497,111};
        int mioIndice=3;
        printf("\n%d\n",mioVettore[mioIndice]);
        printf("\n%d\n",mioIndice[mioVettore]);
        system("PAUSE");
    }
    ho aggiunto stdlib e il PAUSE per il terminale di Windows.

  9. #9
    Utente di HTML.it L'avatar di Freax
    Registrato dal
    Jul 2006
    Messaggi
    460
    aggiungo una estensione dell'esempio precedente visto che con i puntatori ci si diverte :

    codice:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(){
        int mioVettore[5]={56,87,123,497,111};
        int mioIndice=3;
    
        printf("\n%d\n",mioVettore[mioIndice]);
        printf("\n%d\n",mioIndice[mioVettore]);
    
        int* mioPuntatore;
    
        mioPuntatore=(mioIndice+mioVettore);
        printf("\n%d\n",*mioPuntatore);
    
        mioPuntatore=&mioVettore[mioIndice];
        printf("\n%d\n",*mioPuntatore);
    
        mioPuntatore=&mioIndice[mioVettore];
        printf("\n%d\n",*mioPuntatore);
    
        system("PAUSE");
    }

  10. #10
    Gli array non sono puntatori, sono tipi distinti, semplicemente in molte occasioni decadono in puntatori.

    Gli string literals non sono praticamente mai allocati sullo stack, ma in un'area di memoria generalmente di sola lettura, in genere corrispondente ad una particolare sezione dell'eseguibile mappata in memoria.
    Amaro C++, il gusto pieno dell'undefined behavior.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.