'\ 0' e printf () in C


21

In un corso introduttivo di C, ho imparato che durante la memorizzazione delle stringhe vengono archiviate con carattere null \0alla fine di esso. E se volessi stampare una stringa, dì printf("hello")anche se ho scoperto che non termina con la \0seguente dichiarazione

printf("%d", printf("hello"));

Output: 5

ma questo sembra essere incoerente, per quanto ne so che variabili come stringhe vengono memorizzate nella memoria principale e immagino che durante la stampa di qualcosa possa essere memorizzata nella memoria principale, quindi perché la differenza?


1
Oltre al fatto che almeno il tuo codice manca );, cosa intendi mostrare con quel codice? Come hai dimostrato che non finisce con un \0?
glglgl

E cosa c'entra la memoria con cui è immagazzinata?
Tsakiroglou Fotis

In C tutte le stringhe letterali sono in realtà matrici di caratteri, che includono il null-terminator.
Qualche programmatore amico

@glglgl Penso che printf () restituisca il numero di caratteri che dovrebbe stampare sullo schermo.
Ajay Mishra

4
@AjayMishra Sì, e in effetti avrebbe dovuto stampare 5 caratteri. Lo 0 byte finale non viene stampato sullo schermo.
glglgl

Risposte:


13

Il byte null segna la fine di una stringa. Non viene conteggiato nella lunghezza della stringa e non viene stampato quando viene stampata una stringa printf. Fondamentalmente, il byte null indica le funzioni che eseguono la manipolazione delle stringhe quando interrompere.

Il punto in cui vedrai una differenza è se crei un chararray inizializzato con una stringa. L'uso sizeofdell'operatore rifletterà la dimensione dell'array incluso il byte null. Per esempio:

char str[] = "hello";
printf("len=%zu\n", strlen(str));     // prints 5
printf("size=%zu\n", sizeof(str));    // prints 6

Pensavo che la storia sarebbe stata diversa printf(). TBH Non ho idea di come printf()funzioni.
Ajay Mishra

8

printfrestituisce il numero dei caratteri stampati. '\0'non viene stampato - segnala semplicemente che non ci sono più caratteri in questa stringa. Non viene conteggiato anche per la lunghezza della stringa

int main()
{
    char string[] = "hello";

    printf("szieof(string) = %zu, strlen(string) = %zu\n", sizeof(string), strlen(string));
}

https://godbolt.org/z/wYn33e

sizeof(string) = 6, strlen(string) = 5

6

Il tuo presupposto è sbagliato. La tua stringa infatti termina con a \0.

Esso contiene 5 caratteri h, e, l, l, oe il carattere 0.

Ciò che la print()chiamata "interna" genera è il numero di caratteri che sono stati stampati, e questo è 5.


6

In C tutte le stringhe letterali sono in realtà matrici di caratteri, che includono il null-terminator.

Tuttavia, il terminatore null non viene conteggiato nella lunghezza di una stringa (letterale o no) e non viene stampato. La stampa si interrompe quando viene trovato il terminatore null.


Esiste un modo per verificarlo senza memorizzare la stringa in un array?
Ajay Mishra

1
@AjayMishra Beh, la stringa è già in un array (come detto) ... Ma se non ci fosse un terminatore nullo, uscirebbe printfdai limiti della stringa e stamperebbe caratteri "casuali" o "spazzatura", e restituire un numero diverso dalla lunghezza della stringa. Se conosci già la lunghezza della stringa, puoi anche verificare se il carattere in quell'indice è '\0', che funzionerà ma è un comportamento tecnicamente indefinito se la dimensione dell'array non include il terminatore (come in char arr[5] = "hello";, che non aggiungerà il carattere terminatore alla matrice).
Qualche programmatore amico

@AjayMishra Sì, ad esempio, puoi fare char * p = "Hello"; int i = 0; while (p[i] != '\0') { printf("%d: %c", i, p[i]); i++; }e vedere come funziona: mostra le linee con gli indici e il contenuto su quella linea. Dopo l'indice 4, trova il carattere 0 e interrompe il ciclo while. Lì vedi che c'è un carattere 0.
glglgl

6

Tutte le risposte sono davvero buone, ma vorrei aggiungere un altro esempio per completare tutte queste

#include <stdio.h>

int main()
{
    char a_char_array[12] = "Hello world";

    printf("%s", a_char_array);
    printf("\n");

    a_char_array[4] = 0; //0 is ASCII for null terminator

    printf("%s", a_char_array);
    printf("\n");

    return 0;
}

Per coloro che non vogliono provare questo su gdb online, l'output è:

Ciao mondo

Inferno

https://linux.die.net/man/3/printf

È utile capire cosa fa il terminatore di escape? Non è un limite per un array di caratteri o una stringa. È il personaggio che dirà al ragazzo che analizza -STOP, (stampa) analizza fino a qui.

PS: E se lo analizzi e lo stampi come array di caratteri

for(i=0; i<12; i++)
{
    printf("%c", a_char_array[i]);
}
printf("\n");

ottieni:

Inferno mondo

dove, lo spazio dopo la doppia l è il terminatore null, tuttavia, analizzando un array di caratteri, sarà solo il valore di carattere di ogni byte. Se esegui un'altra analisi e stampi il valore int di ciascun byte ("% d%, char_array [i]), vedrai che (ottieni la rappresentazione in codice ASCII) lo spazio bianco ha un valore pari a 0.


4

In Cfunzione printf()restituisce il numero di caratteri stampati, \0è un nullterminatore che viene utilizzato per indicare la fine della stringa in linguaggio c e non esiste un stringtipo incorporato a partire da c++, tuttavia la dimensione dell'array deve essere almeno maggiore del numero chardesiderato immagazzinare.

Ecco il ref: cpp ref printf ()


3

E se volessi stampare una stringa, dì printf ("ciao") anche se ho scoperto che non termina con \ 0 seguendo le istruzioni

printf("%d", printf("hello"));

Output: 5

Tui hai torto. Questa affermazione non conferma che la stringa letterale "hello"non termina con il carattere zero finale '\0'. Questa affermazione ha confermato che la funzione printfgenera elementi di una stringa fino a quando non viene rilevato il carattere di zero finale.

Quando si utilizza una stringa letterale come nell'istruzione precedente, il compilatore crea una matrice di caratteri con la durata di memorizzazione statica che contiene elementi della stringa letterale.

Quindi in realtà questa espressione

printf("hello")

viene elaborato dal compilatore in modo simile al seguente

static char string_literal_hello[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
printf( string_literal_hello );

L'azione della funzione printf in questo si può immaginare nel modo seguente

int printf( const char *string_literal )
{
    int result = 0;

    for ( ; *string_literal != '\0'; ++string_literal )
    {    
        putchar( *string_literal );
        ++result;
    }

    return result;
}

Per ottenere il numero di caratteri memorizzati nella stringa letterale "ciao" puoi eseguire il seguente programma

#include <stdio.h>

int main(void) 
{
    char literal[] = "hello";

    printf( "The size of the literal \"%s\" is %zu\n", literal, sizeof( literal ) );

    return 0;
}

L'output del programma è

The size of the literal "hello" is 6

0

Devi prima cancellare il tuo concetto. Come verrà chiarito quando hai a che fare con l'array, il comando di stampa che stai usando sta solo contando i caratteri che sono posti all'interno della paresi. È necessario nella stringa di matrice che finirà con \ 0


0

Una stringa è un vettore di caratteri. Contiene la sequenza di caratteri che formano la stringa, seguita dalla stringa di caratteri di fine speciale: '\ 0'

Esempio: char str [10] = {'H', 'e', ​​'l', 'l', 'o', '\ 0'};

Esempio: il seguente vettore di caratteri non è una stringa perché non termina con '\ 0'

char str [2] = {'h', 'e'};


Non ci sono vettori in C, immagino.
Ajay Mishra,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.