Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Carattere finale array di caratteri.
Forum - C/C++ - Carattere finale array di caratteri.

Avatar
web_pirate (Normal User)
Rookie


Messaggi: 51
Iscritto: 27/12/2011

Segnala al moderatore
Postato alle 15:38
Mercoledì, 24/10/2012
Salve a tutti, la mia domanda è alquanto tecnica.
Allora, se io dichiaro una variabile char str[]={'a','b','c','d'}; anche se non lo specifico verrà inserito alla fine il valore \0, vero?

PM Quote
Avatar
Poggi Marco (Member)
Guru


Messaggi: 969
Iscritto: 05/01/2010

Segnala al moderatore
Postato alle 16:32
Mercoledì, 24/10/2012
No.
Esistono due modi per inizializzare un vettore char:

1)
Codice sorgente - presumibilmente C/C++

  1. char str[]={'a','b','c','d','\0'};

2)
Codice sorgente - presumibilmente C/C++

  1. char str[]="abcd";



Vedi http://www.cplusplus.com/doc/tutorial/ntcs/.

In questi casi, è consigliabile fare un programmino apposito, per verivicare come funzionano le cose.

PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6378
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 19:37
Mercoledì, 24/10/2012
Testo quotato

Postato originariamente da web_pirate:

Salve a tutti, la mia domanda è alquanto tecnica.



In un forum di questo tipo, tutte le domande sono "tecniche" ...

Testo quotato


se io dichiaro una variabile char str[]={'a','b','c','d'}; ...



La risposta l'hai già avuta, ma bastava controllare con un piccolo test ... che senso ha fare domande così semplici in un forum?

Ultima modifica effettuata da nessuno il 24/10/2012 alle 19:38


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti (uno dei padri fondatori del moderno Calcolo delle probabilità) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
web_pirate (Normal User)
Rookie


Messaggi: 51
Iscritto: 27/12/2011

Segnala al moderatore
Postato alle 22:14
Mercoledì, 24/10/2012
Codice sorgente - presumibilmente C/C++

  1. La risposta l'hai già avuta, ma bastava controllare con un piccolo test ... che senso ha fare domande così semplici in un forum?


Nessuno, lo so che basta un niente per controllare, anche perché non programmo da ieri. Comunque il dubbio è sorto perché sto approfondendo il modo in cui un programma viene eseguito a livello di linguaggio macchina(ovviamente disassemblando il file binario in linguaggio assembly). Il puntatore, non è altro che un indirizzo di memoria che contiene al suo interno un ulteriore indirizzo di memoria, all'interno del quale si trova il dato che ci interessa. Ora, se la risposta che ha dato Marco è vera, come supponevo prima di porla, l'array di char NON dovrebbe finire con il valore '\0', come si necessita per una stringa. Ora, se io dichiaro un array con char str[]={'a','b','c','d'}, e poi la riga seguente è ptr = str;, dove ptr è stato dichiarato con char *ptr, il puntatore punterà all'inizio dell'indirizzo di memoria occupato da str. Se però vado a stampare il valore a cui punta il puntatore con printf("%s", ptr), non dovrei avere un qualche errore di segmentazione? Il puntatore non dovrebbe fermarsi quando incontra il valore '\0' che, come ha detto Marco, non c'è, dal momento che va dichiarato anche quello? Ecco perché ho detto che è "alquanto" tecnica la domanda :D

PM Quote
Avatar
Poggi Marco (Member)
Guru


Messaggi: 969
Iscritto: 05/01/2010

Segnala al moderatore
Postato alle 22:57
Mercoledì, 24/10/2012
In effetti, il c ha un comportamento strano...
Nel caso si dichiari char str[]={'a','b','c','d'}; a volte, viene "aggiunto" il carattere '\0' alla fine.
In ogni caso, il compilatore usa la lunghezza dell' inizializzatore, per determinare quanta memoria allocare.  
In questo caso, la stringa ha lunghezza pari a 4.

PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6378
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 7:34
Giovedì, 25/10/2012
Testo quotato

Postato originariamente da web_pirate:
Ora, se la risposta che ha dato Marco è vera, come supponevo prima di porla, l'array di char NON dovrebbe finire con il valore '\0'



Ed è così. Il compilatore NON pone uno '\0' alla fine dell'array di char. Che è quello che conta.

Testo quotato

non dovrei avere un qualche errore di segmentazione?



Non si ottiene sempre un errore di segmentazione proprio perché non è detto che alla sequenza di char, in memoria da qualche parte, non si incontri uno '\0'. E proprio nell'esempio che hai indicato, c'è un'alta probabilità di incontrarlo perché il puntatore di cui parli potrà contenerlo.

Per capirci, se in memoria hai l'array abcd avrai i valori

61 62 63 64

e dopo seguirà l'indirizzo del puntatore ad esempio 00417000

00 70 41 00

quindi avrai

61 62 63 64 00 70 41 00

e come vedi dopo l'array ci sarà lo 00 binario che verrà interpretato come chiusura della stringa ma non c'entra nulla con l'array di char.

@Poggi Marco
Il C non ha un comportamento strano. E' un comportamento preciso dettato da regole.
Il carattere '\0' non viene mai aggiunto in quanto "terminatore" della stringa ma vengono aggiunti 00 binari ai dati eventualmente per "allinearli" ai 32 bit (solo per una questione di allineamento ai 32 bit dei dati in memoria per permettere un accesso veloce alle CPU).

Quindi, se aggiungi un altro char all'array, ad esempio abcde, non avrai

61 62 63 64 65 00 70 41 00

perché in questo modo il puntatore str non sarà allineato ai 32 bit. Il compilatore quindi introdurrà dei byte a 00 per allineare il puntatore, ovvero

61 62 63 64 65 00 00 00 00 70 41 00

in modo da avere 4 byte + 4 byte + 4 byte

Quei byte in più saranno "sprecati" ma permetteranno alla CPU un accesso più efficiente e veloce ai dati in memoria.

In molti casi, quello spazio può essere utilizzato (il compilatore ottimizza) ... ad esempio, se scrivi

char str[]={'a','b','c','d','e'};
char *ptr = str;
char x = '*';

quel singolo carattere '*' potrà essere "attaccato" all'array per sfruttare lo spazio sprecato. Avrai in memoria

61 62 63 64 65 2A 00 00 00 70 41 00

Altra storia se scrivi

char str[]="abcde";
char *ptr = str;
char x = '*';

in quanto il terminatore verrà esplicitamente aggiunto (in quanto si tratta di una stringa) e quindi

61 62 63 64 65 00 2A 00 00 70 41 00

Ovviamente altre considerazioni vanno fatte se tutti questi dati sono locali (e quindi allocati nello stack) anche se rimane il fatto che il terminatore non viene aggiunto all'array di char e anche in questo caso la presenza di 00 seguenti potrà essere casuale.

Ultima modifica effettuata da nessuno il 25/10/2012 alle 8:00


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti (uno dei padri fondatori del moderno Calcolo delle probabilità) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
Poggi Marco (Member)
Guru


Messaggi: 969
Iscritto: 05/01/2010

Segnala al moderatore
Postato alle 10:07
Giovedì, 25/10/2012
Grazie a nessuno per il suo chiarimento.

PM Quote
Avatar
web_pirate (Normal User)
Rookie


Messaggi: 51
Iscritto: 27/12/2011

Segnala al moderatore
Postato alle 13:41
Giovedì, 25/10/2012
Ok. Grazie per la spiegazione. Solo che non ho capito una cosa della tua spiegazione.
Codice sorgente - presumibilmente C/C++

  1. Per capirci, se in memoria hai l'array abcd avrai i valori
  2.  
  3. 61 62 63 64
  4.  
  5. e dopo seguirà l'indirizzo del puntatore ad esempio 00417000
  6.  
  7. 00 70 41 00


Quando dici che seguirà l'indirizzo del puntatore, vuol dire che all'interno dell'indirizzo di memoria di str ci saranno i 4 byte di acbd e l'indirizzo del puntatore ptr? Quindi se l'indirizzo di ptr è 0x097a65b3 e contiene a sua volta 0x88bfff22(indirizzo di str), all'interno di 0x88bfff22 ci sarà 61 62 63 64 0x097a65b3?

PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6378
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 13:50
Giovedì, 25/10/2012
Voglio dire che str inizia all'indirizzo 00417000. La singole celle conterranno

00417000 61
00417001 62
00417002 63
00417003 64

Seguirà il valore di ptr che sarà posto a partire dall'indirizzo 00417004 e conterrà il valore dell'indirizzo di str

00417004 00
00417005 70
00417006 41
00417007 00



Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti (uno dei padri fondatori del moderno Calcolo delle probabilità) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote