Skip to content

Qual è la logica delle stringhe con terminazione nulla?

Restate sintonizzati perché in questo articolo troverete la disposizione che cercate.Questo post è stato testato dai nostri esperti per garantire la qualità e la veridicità dei nostri contenuti.

Soluzione:

Dalla bocca del cavallo

Nessuno dei BCPL, B o C supporta
i dati dei caratteri in modo deciso nel
linguaggioe; ognuno tratta le stringhe come
come vettori di interi e
regole generali con alcune convenzioni.
convenzioni. Sia in BCPL che in B un
letterale di stringa denota l'indirizzo di
un'area statica inizializzata con i
caratteri della stringa, impacchettati in
celle. In BCPL, il primo byte impacchettato
contiene il numero di caratteri della
della stringa; in B, non c'è un conteggio
e le stringhe sono terminate da un
carattere speciale, che B scrive
*e. Questa modifica è stata fatta in parte
per evitare la limitazione della lunghezza
di una stringa causata dal mantenimento del
in uno slot a 8 o 9 bit e in parte perché
in parte perché il mantenimento del conteggio
conteggio sembrava, secondo la nostra esperienza, meno
meno conveniente rispetto all'uso di un terminatore.

Dennis M Ritchie, Sviluppo del linguaggio C

Il C non ha una stringa come parte del linguaggio. Una 'stringa' in C è solo un puntatore a char. Quindi forse state facendo la domanda sbagliata.

"Qual è la ragione per cui non c'è un tipo di stringa" potrebbe essere più pertinente. Vorrei far notare che il C non è un linguaggio orientato agli oggetti e ha solo tipi di valore di base. Una stringa è un concetto di livello superiore che deve essere implementato combinando in qualche modo valori di altri tipi. Il C è a un livello di astrazione inferiore.

alla luce dell'impetuoso temporale sottostante:

Voglio solo sottolineare che non sto cercando di dire che questa è una domanda stupida o cattiva, o che il modo C di rappresentare le stringhe è la scelta migliore. Sto cercando di chiarire che la domanda sarebbe più concisa se si tenesse conto del fatto che il C non ha alcun meccanismo per differenziare una stringa come tipo di dati da un array di byte. È questa la scelta migliore alla luce della potenza di elaborazione e di memoria dei computer di oggi? Probabilmente no. Ma il senno di poi è sempre 20/20 e tutto il resto 🙂

La domanda è posta come un Length Prefixed Strings (LPS) contro zero terminated strings (SZ) ma soprattutto di esporre i vantaggi delle stringhe con prefisso di lunghezza. Questo può sembrare eccessivo, ma per essere onesti dovremmo considerare anche gli svantaggi di LPS e i vantaggi di SZ.

Per come la vedo io, la domanda potrebbe anche essere intesa come un modo distorto per chiedere "quali sono i vantaggi delle stringhe a terminazione zero?".

Vantaggi (a mio avviso) delle stringhe a terminazione zero:

  • molto semplice, non c'è bisogno di introdurre nuovi concetti nel linguaggio, gli array di char
    array e puntatori di caratteri.
  • il linguaggio principale include solo un minimo di zucchero sintattico per convertire
    qualcosa tra doppi apici in un
    un gruppo di caratteri (in realtà un gruppo di
    byte). In alcuni casi può essere usato
    per inizializzare cose completamente
    non correlate al testo. Per esempio xpm
    formato di file immagine è un'origine C valida
    che contiene dati di immagini codificati come
    stringa.
  • a proposito, si può mettere uno zero in un letterale di stringa, il compilatore
    aggiungerà un altro alla fine del letterale: "thisisvalidC".
    È una stringa? O quattro stringhe? O un gruppo di byte...
  • implementazione piatta, nessuna indirezione nascosta, nessun intero nascosto.
  • nessuna allocazione di memoria nascosta (beh, alcune famigerate funzioni non
    standard come strdup
    eseguono l'allocazione, ma questa è per lo più
    una fonte di problemi).
  • nessun problema specifico per hardware di piccole o grandi dimensioni (immaginate l'onere di
    gestire 32 bit di lunghezza del prefisso su microcontrollori a 8
    microcontrollori a 8 bit, o le
    restrizioni di limitare la dimensione delle stringhe
    a meno di 256 byte, era un problema che ho avuto con Turbo Pascal eoni fa).
  • L'implementazione della manipolazione delle stringhe è solo una manciata di
    funzioni di libreria molto semplici
  • efficiente per l'uso principale delle stringhe: testo costante letto
    sequenzialmente da un inizio noto
    (per lo più messaggi all'utente).
  • lo zero di terminazione non è nemmeno obbligatorio, tutti gli strumenti necessari
    per manipolare i caratteri come un gruppo di
    byte sono disponibili. Quando si esegue l'inizializzazione di
    inizializzazione degli array in C, si può
    evitare il terminatore NUL. Basta
    impostare la dimensione giusta. char a[3] =
    "foo";
    è valido in C (non in C++) e
    non metterà uno zero finale in a.
  • coerente con il punto di vista unix "tutto è file", compresi i "file" che non hanno una lunghezza intrinseca.
    "file" che non hanno una lunghezza intrinseca
    come stdin e stdout. È bene ricordare che le primitive di lettura e scrittura di open sono implementate
    a un livello molto basso. Non sono chiamate di libreria, ma di sistema. E la stessa API viene utilizzata
    per i file binari o di testo. Le primitive di lettura dei file ottengono un indirizzo di buffer e una dimensione e restituiscono la nuova dimensione.
    la nuova dimensione. È possibile utilizzare le stringhe come buffer per la scrittura. L'uso di un altro tipo di rappresentazione
    implicherebbe l'impossibilità di usare una stringa letterale come buffer per l'output, oppure
    si dovrebbe fare in modo che abbia un comportamento molto strano quando viene lanciata a char*. Ovvero
    di non restituire l'indirizzo della stringa, ma di restituire i dati effettivi.
  • È molto facile manipolare i dati di testo letti da un file in-place, senza inutili copie del buffer,
    basta inserire gli zeri nei punti giusti (beh, non proprio con il C moderno, dato che oggi le stringhe con doppi apici sono array di const char, solitamente conservati in un segmento di dati non modificabile).
  • La preposizione di alcuni valori int di qualsiasi dimensione implicherebbe problemi di allineamento. La lunghezza iniziale
    iniziale dovrebbe essere allineata, ma non c'è motivo di farlo per i dati dei caratteri (e
    di nuovo, forzare l'allineamento delle stringhe implicherebbe problemi nel trattarle come un gruppo di
    byte).
  • La lunghezza è nota in fase di compilazione per le stringhe letterali costanti (sizeof). Quindi perché si dovrebbe
    perché qualcuno vorrebbe memorizzarla in memoria anteponendola ai dati reali?
  • In un certo senso C sta facendo come (quasi) tutti gli altri, le stringhe sono viste come array di char. Poiché la lunghezza degli array non è gestita da C, è logico che la lunghezza non sia gestita nemmeno per le stringhe. L'unica cosa sorprendente è l'aggiunta di 0 alla fine, ma è solo a livello di linguaggio di base quando si digita una stringa tra doppi apici. Gli utenti possono benissimo chiamare le funzioni di manipolazione delle stringhe passando la lunghezza, o anche usare la semplice memcopia. Le SZ sono solo una funzione. Nella maggior parte degli altri linguaggi la lunghezza degli array è gestita, è logico che sia lo stesso per le stringhe.
  • Nei tempi moderni, comunque, i set di caratteri da 1 byte non sono sufficienti e spesso si ha a che fare con stringhe unicode codificate in cui il numero di caratteri è molto diverso dal numero di byte. Ciò implica che gli utenti probabilmente vorranno più della "sola dimensione", ma anche altre informazioni. Mantenere la lunghezza non dà nulla (in particolare non c'è un posto naturale per memorizzarle) riguardo a queste altre utili informazioni.

Detto questo, non c'è bisogno di lamentarsi nel raro caso in cui le stringhe C standard siano effettivamente inefficienti. Le librerie sono disponibili. Se seguissi questa tendenza, dovrei lamentarmi del fatto che il C standard non include alcuna funzione di supporto per le regex... ma in realtà tutti sanno che non è un vero problema, dato che sono disponibili librerie per questo scopo. Quindi, quando si vuole l'efficienza della manipolazione delle stringhe, perché non usare una libreria come bstring? O anche le stringhe del C++?

EDIT: Recentemente ho dato un'occhiata alle stringhe D. È abbastanza interessante vedere che la soluzione scelta non è né un prefisso di dimensione, né la terminazione zero. Come in C, le stringhe letterali racchiuse tra doppi apici sono solo una scorciatoia per gli array di char immutabili, e il linguaggio ha anche una parola chiave stringa che significa (array di char immutabili).

Ma gli array D sono molto più ricchi di quelli C. Nel caso degli array statici, la lunghezza è nota a tempo di esecuzione, quindi non è necessario memorizzarla. Il compilatore la conosce a tempo di compilazione. Nel caso degli array dinamici, la lunghezza è disponibile, ma la documentazione di D non indica dove viene conservata. Per quanto ne sappiamo, il compilatore potrebbe scegliere di tenerla in qualche registro o in qualche variabile memorizzata lontano dai dati dei caratteri.

Nei normali array di caratteri o nelle stringhe non letterali non c'è uno zero finale, quindi il programmatore deve metterlo da solo se vuole chiamare una funzione C da D. Nel caso particolare delle stringhe letterali, tuttavia, il compilatore di D mette comunque uno zero alla fine di ogni stringa (per consentire un facile cast in stringhe C per facilitare la chiamata di una funzione C?), ma questo zero non fa parte della stringa (D non lo conta nella dimensione della stringa).

L'unica cosa che mi ha un po' deluso è che le stringhe dovrebbero essere utf-8, ma la lunghezza apparentemente restituisce ancora un numero di byte (almeno è vero sul mio compilatore gdc) anche quando si usano caratteri multi-byte. Non mi è chiaro se si tratti di un bug del compilatore o se sia stato fatto apposta. (OK, probabilmente ho scoperto cosa è successo. Per dire al compilatore D che i tuoi sorgenti usano utf-8 devi mettere uno stupido segno di ordine dei byte all'inizio. Ho scritto stupido perché non conosco nessun editor che lo faccia, specialmente per UTF-8 che dovrebbe essere compatibile con ASCII).

Ti mostriamo commenti e punteggi

Se hai qualche domanda e modo di beneficiare della nostra scrittura, ti invitiamo a scrivere un'interpretazione e la interpreteremo volentieri.



Utilizzate il nostro motore di ricerca

Ricerca
Generic filters

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.