Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 13
  1. #1
    Utente di HTML.it
    Registrato dal
    Sep 2009
    residenza
    Roma
    Messaggi
    371

    [c] dubbio banalissimo(direi elementare)

    Domanda banalissima, se ho un pezzo di codice come questo:
    Codice PHP:
    charretStr()
        {
        return 
    "ciao";
        }

    int main()
        {
        
    char *str;
        
    str=retStr();
        
    printf("%s\n"str);
        } 
    Ora mi sembra di ricordare che un codice simile dovrebbe dare problemi in quanto la stringa "ciao" viene allocata nello stack e dovrebbe quindi venire cancellata appena si ritorna dalla funzione, come mai invece avviene correttamente la stampa?
    dipende semplicemente dal fatto che fino al momento della stampa non è ancora stata toccata quella zona di memoria o sono io che ricordo male riguardo l'esistenza di un problema simile?

  2. #2
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,462
    In questo caso non allochi nulla nello stack. La stringa è una costante e quindi viene inglobata staticamente nell'eseguibile.
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  3. #3
    Utente di HTML.it
    Registrato dal
    Sep 2009
    residenza
    Roma
    Messaggi
    371
    a ok, e se invece fosse stato
    Codice PHP:
    charretStr()
        {
        
    char *str="ciao"
        
    return str;
        }

    int main()
        {
        
    char *str;
        
    str=retStr();
        
    printf("%s\n"str);
        } 
    oppure

    Codice PHP:
    charretStr(charstr)
        {
        return 
    str;
        }

    int main()
        {
        
    char *str;
        
    str=retStr("ciao");
        
    printf("%s\n"str);
        } 
    in questi 2 casi quale sarebbe stato l'esito?

  4. #4
    In generale gli string literal hanno la stessa lifetime degli array globali - in altre parole, è garantito che sopravvivano per tutta la durata del programma.

    Per inciso, lì retStr dovrebbe restituire un const char *, dato che gli string literal non sono modificabili (a seconda dei casi, puoi ottenere un crash o comportamenti inspiegabili del programma).
    a ok, e se invece fosse stato [...]
    In entrambi i casi non c'è problema (salvo la precisazione del const di prima nel primo caso).
    Nel primo caso assegni prima il puntatore al literal ad un altro puntatore e poi lo restituisci - perché dovrebbe essere un problema? Il punto non è la durata di vita dei puntatori (che vengono copiati), ma quella di ciò a cui puntano; qui "ciao" è un literal, quindi sopravvive per tutta la durata del programma, ergo puoi passarlo in giro come ti pare, tanto è memoria che non viene deallocata.

    Nel secondo caso, restituisci una copia del puntatore che ti viene passato; vale un discorso analogo: se il puntatore puntava a qualcosa che esisteva prima della chiamata a funzione, non è che questo qualcosa è improvvisamente sparito... di nuovo, non conta il puntatore, ma ciò a cui punta.

    Il caso problematico è questo:
    codice:
    char * retStr()
    {
        char str[]="ciao";
        return str;
    }
    In questo caso sto restituendo un puntatore al primo elemento di un array locale a retStr, che cessa di esistere nel momento in cui la funzione termina, per cui il chiamante si ritrova restituito un puntatore a della roba che non esiste più, per cui è chiaro che in questo caso possono sorgere problemi.
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Utente di HTML.it
    Registrato dal
    Sep 2009
    residenza
    Roma
    Messaggi
    371
    chiarissimo, stoltanto non ho capito una cosa, qual'è la differenza fra
    codice:
    char* retStr()
        {
        char *str="ciao"
        return str;
        }
    e questo?
    codice:
    char * retStr()
    {
        char str[]="ciao";
        return str;
    }
    Non sono in entrambi i casi array di char creati localmente alla funzione?

  6. #6
    No.
    codice:
    char * str="ciao";
    assegna a str l'indirizzo del literal "ciao", che sta in una locazione di memoria valida per tutta la durata del programma. Come già detto sopra, comunque, dovrebbe essere
    codice:
    const char * str="ciao";
    dato che la modifica della stringa literal puntata da str risulta in undefined behavior (e infatti assegnare un literal ad un char * passa per una conversione deprecata)

    Invece
    codice:
    char str[]="ciao";
    è la sintassi abbreviata per
    codice:
    char str[5]={'c', 'i', 'a', 'o', '\0'};
    ovvero, crea un array locale alla funzione corrente, di dimensione tale da poter accogliere tutta la stringa "ciao" e lo inizializza con la stringa in questione.

    Le due cose sono estremamente diverse: in un caso hai un puntatore ad un literal - ovvero ad un array globale di char non modificabile ma valido per tutta l'esecuzione del programma; nell'altro, hai un array locale di char, modificabile e limitato allo scope corrente.
    Amaro C++, il gusto pieno dell'undefined behavior.

  7. #7
    Utente di HTML.it
    Registrato dal
    Sep 2009
    residenza
    Roma
    Messaggi
    371
    ok, per capire meglio c'è una qualche fonte da cui mi consigli di studiare questi particolari?
    non ho mai trovato spiegazioni cosi approfondite, e vorrei cercare di capire il più possibile...

  8. #8
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,462
    Un buon libro di C/C++ dovrebbe fornire queste indicazioni ...

    Il problema è che molte volte queste cose sono scritte, ma non si prendono in considerazione e si passa subito a scrivere codice ....
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  9. #9
    Utente di HTML.it
    Registrato dal
    Sep 2009
    residenza
    Roma
    Messaggi
    371
    allora ora vedrò di acquistare "The C++ Programming Language" di Stroustrup, non è incentrato sul C ma comunque credo spieghi anche queste cose, e già che ci sono approfondisco anche il C++

  10. #10
    Uhm, occhio che C e C++, nonostante condividano un subset fondamentale, sono piuttosto diversi come modo di utilizzo e "filosofia di fondo" (specie il cosiddetto C++ moderno).
    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 © 2024 vBulletin Solutions, Inc. All rights reserved.