DOMANDA stringhe e puntatori in C

cuttyflam

Nuovo Utente
21
2
Sto iniziando a studiare il linguaggio C.
Il mio testo di riferimento dice che il nome di una stringa è un puntatore
e che quindi è possibile fare questa uguaglianza p(con variabile char *p)=s(stringa) e non p=&s.
La domanda è questa.
Se con p+i riesco ad accedere a tutti gli indirizzi di s questo vuol dire che la stringa e quindi anche un file di testo... viene memorizzata in memoria in indirizzi successivi, non in modo frammentato?
 

_Achille

Utente Èlite
3,067
725
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
HDD
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
GPU
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
PSU
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
OS
Windows 10 Pro
Una stringa un file di testo??!

Una stringa in C è un array di char terminato da un '\0', ossia risiede nella memoria volatile e non ha altre caratteristiche (path, metadati, ecc…) che ha un file di testo.

Con p + i non accedi a tutti gli indirizzi di s, ma all’i-esimo elemento della stringa (o anche a zone fuori dalla stringa…).

L’ assegnazione è possibile perché gli array possono implicitamente decadere in puntatori in alcuni casi, e questo è uno di quelli.

Un altro, ad esempio, è quello di un argomento in una funzione.
C:
void f(char s[]);
void f(char s[10]);
void f(char *s);
Sono tutte dichiarazioni equivalenti che decadono nell’ultimo caso.

Un caso, invece, in cui non avviene il cast implicito a puntatore è con l’operatore sizeof.

Inoltre l’operatore [] funziona esattamente come l’aritmetica dei puntatori, quindi s[i] è equivalente a *(p + i) e quindi a p[i].
 
Ultima modifica:

cuttyflam

Nuovo Utente
21
2
Una stringa un file di testo??!

Una stringa in C è un array di char terminato da un '\0', ossia risiede nella memoria volatile e non ha altre caratteristiche (path, metadati, ecc…) che ha un file di testo.

Con p + i non accedi a tutti gli indirizzi di s, ma all’i-esimo elemento della stringa (o anche a zone fuori dalla stringa…).

Questo è possibile perché gli array possono implicitamente decadere in puntatori in alcuni casi, e questo è uno di quelli.

Un altro, ad esempio, è quello di un argomento in una funzione.
C:
void f(char s[]);
void f(char s[10]);
void f(char *s);
Sono tutte dichiarazioni equivalenti che decadono nell’ultimo caso.

Un caso, invece, in cui non avviene il cast implicito a puntatore è con l’operatore sizeof.

Grazie per la sua risposta.
In un programma in ambiente dos, ad esempio, potrei dare in input invece di una stringa da battere al terminale un intero file di testo digitando eseguibile(file.exe) < textfile(nome del file di testo). In pratica il file di testo diventa la mia stringa caricata in memoria. Da qui la mia domanda. Questa stringa, anche molto lunga, è caricata in memoria in indirizzi adiacenti, non frammentati?
 

_Achille

Utente Èlite
3,067
725
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
HDD
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
GPU
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
PSU
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
OS
Windows 10 Pro
Grazie per la sua risposta.
In un programma in ambiente dos, ad esempio, potrei dare in input invece di una stringa da battere al terminale un intero file di testo digitando eseguibile(file.exe) < textfile(nome del file di testo). In pratica il file di testo diventa la mia stringa caricata in memoria. Da qui la mia domanda. Questa stringa, anche molto lunga, è caricata in memoria in indirizzi adiacenti, non frammentati?
Tu vuoi dare come argomento il path al file di testo?
Troverai quell’argomento nell’array di stringhe argv alla posizione n. 1.

Quella è una stringa, con tutte le sue caratteristiche
 

cuttyflam

Nuovo Utente
21
2
Non c'entra il path. Con quel comando da terminale il programma legge esclusivamente i caratteri del file e li memorizza nel formato richiesto dal programma(come una successione di char oppure come una stringa).
 

_Achille

Utente Èlite
3,067
725
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
HDD
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
GPU
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
PSU
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
OS
Windows 10 Pro
Non c'entra il path. Con quel comando da terminale il programma legge esclusivamente i caratteri del file e li memorizza nel formato richiesto dal programma(come una successione di char oppure come una stringa).
Scusami eh, e come accederesti al file dal programma? Cosa fornisci come argomento?
 

cuttyflam

Nuovo Utente
21
2
Mettiamo che il compilatore generi un programma es_1.exe da un file es_1.c e che nella stessa directory esista un file di testo di nome testo_1.txt.
Dando da terminale il comando es_1 < testo_1.txt il sistema operativo dos da in input al programma numeri, caratteri o stringhe contenute nel file testo_1.txt. Testato personalmente con la funzione scanf. Il mio scanf normalmente legge dati da tastiera, ma dando quel comando(es_1 < testo_1.txt) esternamente(sull'eseguibile) legge i dati dal file.
 

_Achille

Utente Èlite
3,067
725
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
HDD
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
GPU
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
PSU
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
OS
Windows 10 Pro
Quindi "testo_1.txt" è su argv[2] ed è un path, relativo, al file.
 

cuttyflam

Nuovo Utente
21
2
Figurati che non ancora studio i parametri da passare ad un programma in C. Non so nemmeno cosa sia argv. Fa prima se si legge la pag.24 di Al Kelley e Ira Pohl 'C Didattica e Programmazione' 4°edizione.
 
Ultima modifica:

_Achille

Utente Èlite
3,067
725
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
HDD
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
GPU
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
PSU
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
OS
Windows 10 Pro
Figurati che non ancora studio i parametri da passare ad un programma in C. Non so nemmeno cosa sia argv. Fa prima se si legge la pag.24 di Al Kelley e Ira Pohl 'C Didattica e Programmazione' 4°edizione.
Non darmi del lei ?

Non ho ancora capito quello che devi fare, quello che vuoi fare e cosa hai studiato di C.
Se riesci allega il testo dell’esercizio.
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,208
1,845
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Mi sa che stai mettendo assieme un pò di cose...

Ciò di cui stai parlando è <, che ti consente di redirezionare lo standard input.
Quindi se fai una cosa come questa:

C:
#include <stdio.h>

int main() {
    char str[10] = {0};
    scanf("%s", str);
    printf("String: %s", str);
    return 0;
}

e lo esegui in questo modo es.exe < es.txt, vedrai il contenuto del file.

Quindi...
Se con p+i riesco ad accedere a tutti gli indirizzi di s questo vuol dire che la stringa e quindi anche un file di testo... viene memorizzata in memoria in indirizzi successivi, non in modo frammentato?

Non ho ben capito che vuoi dire.
La stringa non è un file di testo, come diceva Achille. E tu non stai accedendo ad un file, in quanto la scanf() - in quel caso - invece che attendere il tuo input da tastiera, risente della redirezione. Infatti se prima del return metti un "getchar()", vedrai tu stesso che il programma terminerà senza attendere.

Cambiando il codice in questo modo:
C:
#include <stdio.h>

int main() {
    char str[10] = {0};
    scanf("%s", str);

    printf("String: %s", str);
    
    freopen("CON", "r", stdin);
    getchar();
  
    return 0;
}

torni ad utilizzare la keyboard come stdin.
 
  • Mi piace
Reazioni: BAT e Mursey

cuttyflam

Nuovo Utente
21
2
Ciò di cui stai parlando è <, che ti consente di redirezionare lo standard input.
Quindi se fai una cosa come questa:

C:
#include <stdio.h>

int main() {
    char str[10] = {0};
    scanf("%s", str);
    printf("String: %s", str);
    return 0;
}

e lo esegui in questo modo es.exe < es.txt, vedrai il contenuto del file.

Corretto, il contenuto del file viene quindi memorizzato nella variabile stringa str.
La mia domanda è: la stringa, che può essere molto grande per l'appunto, viene memorizzata in uno spazio di memoria continuo, non frammentato come avviene comunemente la memorizzazione sugli hard disk, con pezzi di file da una parte e pezzi dall'altra?
Mi spiego meglio. Se un puntatore p ha lo stesso indirizzo di una stringa str, p+i mi darà lo stesso indirizzo di str di i(non riesco a mettere le quadri) per ogni i che appartiene alla lunghezza della stringa? La stringa infatti potrebbe essere indicizzata come avviene per gli hard disk, ma il puntatore p non conoscerebbe questa indicizzazione della stringa. La mia domanda in pratica nasce perché sono un assiduo deframmentatore di hard disk.
 

theprogrammer.99

Nuovo Utente
96
34
La domanda non ha molto senso ... la memoria (in questo caso è allocata nello stack) ovviamente è contigua. Il file e la deframmentazione non c'entrano proprio nulla,
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,208
1,845
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
No aspetta un momento, lascia perdere gli hard disk (che poi dipende da altri fattori ciò che dici, come il file system utilizzato).

Innanzitutto se la stringa è davvero molto grande, non puoi utilizzare lo stack (come ho fatto nel mio esempio), ma dovrai allocare memoria sufficiente (utilizzando malloc/calloc).
La memoria è contigua:

char str[4] = "ciao"; str[0] = 'c'; str[1] = 'i'; str[2] = 'a'; str[3] = 'o';

Allo stesso modo se utilizzi l'aritmetica dei puntatori è uguale.
Anche se allochi memoria nell'heap con calloc/malloc viene allocata memoria virtuale contigua.

Se allochi sullo stack devi creare uno stack grande abbastanza (attenzione perchè c'è un limite... 1MB se non erro, fatto salvo specifiche differenti al momento della compilazione), altrimenti andrai a scrivere in aree di memoria adiacenti.
Usando sempre l'esempio qui sopra: se in str (che è grande 4byte) ne vai a copiare 10, i 6byte in eccesso vanno a sovrascrivere altre aree dello stack (il che significa che potresti sovrascrivere anche delle variabili che hai dichiarato dopo, o altro ancora). Diciamo che sei fortunato quando crasha, perchè diversamente è difficile trovare l'errore...

Le quadre che usi per indirizzare sono solo "zucchero sintattico". E non avviene nessun bounds-checking; se scrivi *(str+100), verrà calcolato l'indirizzo str+100.

Diciamo che l'indirizzo virtuale di str è 0x1234.
Codice:
str[0] è uguale a *(str+0) -> 0x1234 + 0 = 0x1234
str[1] è uguale a *(str+1) -> 0x1234 + 1 = 0x1235
...

a basso livello infatti avviene una cosa come questa:
[str + (i * sizeof(char))]


Inutile comunque dire che è un modo scorretto per leggere da file (quello che stai utilizzando). Devi ottenere un handle al file e leggerne il contenuto.
 

cuttyflam

Nuovo Utente
21
2
La domanda non ha molto senso ... la memoria in questo caso è allocata nello stack e ovviamente è contigua. Il file e la deframmentazione non c'entrano proprio nulla,

Quindi in memoria i dati(tutto ciò che viene caricato in memoria?) si memorizzano in spazi contigui. Non lo sapevo. Grazie.
Post unito automaticamente:

No aspetta un momento, lascia perdere gli hard disk (che poi dipende da altri fattori ciò che dici, come il file system utilizzato).

Innanzitutto se la stringa è davvero molto grande, non puoi utilizzare lo stack (come ho fatto nel mio esempio), ma dovrai allocare memoria sufficiente (utilizzando malloc/calloc).
La memoria è contigua:

char str[4] = "ciao"; str[0] = 'c'; str[1] = 'i'; str[2] = 'a'; str[3] = 'o';

Allo stesso modo se utilizzi l'aritmetica dei puntatori è uguale.
Anche se allochi memoria nell'heap con calloc/malloc viene allocata memoria virtuale contigua.

Se allochi sullo stack devi creare uno stack grande abbastanza (attenzione perchè c'è un limite... 1MB se non erro, fatto salvo specifiche differenti al momento della compilazione), altrimenti andrai a scrivere in aree di memoria adiacenti.
Usando sempre l'esempio qui sopra: se in str (che è grande 4byte) ne vai a copiare 10, i 6byte in eccesso vanno a sovrascrivere altre aree dello stack (il che significa che potresti sovrascrivere anche delle variabili che hai dichiarato dopo, o altro ancora). Diciamo che sei fortunato quando crasha, perchè diversamente è difficile trovare l'errore...

Le quadre che usi per indirizzare sono solo "zucchero sintattico". E non avviene nessun bounds-checking; se scrivi *(str+100), verrà calcolato l'indirizzo str+100.

Diciamo che l'indirizzo virtuale di str è 0x1234.
Codice:
str[0] è uguale a *(str+0) -> 0x1234 + 0 = 0x1234
str[1] è uguale a *(str+1) -> 0x1234 + 1 = 0x1235
...

a basso livello infatti avviene una cosa come questa:
[str + (i * sizeof(char))]


Inutile comunque dire che è un modo scorretto per leggere da file (quello che stai utilizzando). Devi ottenere un handle al file e leggerne il contenuto.
Non sono in grado di seguirti per ora. Quindi le funzioni malloc e calloc hanno a che fare con la gestione della memoria estesa(è quella che i programmatori chiamano Heap?)?
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili