'\ 0' dan printf () di C

21

Dalam kursus pengantar C, saya telah belajar bahwa saat menyimpan string disimpan dengan karakter nol \0di akhir. Tetapi bagaimana jika saya ingin mencetak string, katakan printf("hello")meskipun saya telah menemukan bahwa itu tidak berakhir dengan \0mengikuti pernyataan

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

Output: 5

tetapi ini tampaknya tidak konsisten, sejauh yang saya tahu bahwa variabel seperti string disimpan dalam memori utama dan saya kira saat mencetak sesuatu itu mungkin juga disimpan dalam memori utama, lalu mengapa bedanya?

Ajay Mishra
sumber
1
Selain fakta bahwa kode Anda setidaknya terlewatkan );, apa yang ingin Anda tunjukkan dengan kode itu? Bagaimana Anda membuktikan bahwa itu tidak berakhir dengan \0?
glglgl
Dan apa memori yang tersimpan, ada hubungannya dengan itu?
Tsakiroglou Fotis
Dalam C semua string literal benar-benar array karakter, termasuk null-terminator.
Beberapa programmer Bung
@glglgl Saya pikir printf () mengembalikan jumlah karakter yang seharusnya dicetak di layar.
Ajay Mishra
4
@AjayMishra Ya, dan memang seharusnya sudah dicetak 5 karakter. Terminasi 0 byte tidak dicetak di layar.
glglgl

Jawaban:

13

Bita nol menandai akhir suatu string. Itu tidak dihitung dalam panjang string dan tidak dicetak ketika string dicetak dengan printf. Pada dasarnya, byte nol memberitahu fungsi yang melakukan manipulasi string kapan harus berhenti.

Di mana Anda akan melihat perbedaannya adalah jika Anda membuat chararray yang diinisialisasi dengan string. Menggunakan sizeofoperator akan mencerminkan ukuran array termasuk byte nol. Sebagai contoh:

char str[] = "hello";
printf("len=%zu\n", strlen(str));     // prints 5
printf("size=%zu\n", sizeof(str));    // prints 6
dbush
sumber
Saya pikir ceritanya akan berbeda printf(). TBH Saya tidak tahu cara printf()kerjanya.
Ajay Mishra
8

printfmengembalikan jumlah karakter yang dicetak. '\0'tidak dicetak - itu hanya menandakan bahwa tidak ada lagi karakter dalam string ini. Itu tidak dihitung terhadap panjang string juga

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
P__J__
sumber
6

Asumsi Anda salah. Tali Anda memang diakhiri dengan a \0.

Ini berisi dari 5 karakter h, e, l, l, odan 0 karakter.

Apa yang dihasilkan oleh print()panggilan "dalam" adalah jumlah karakter yang dicetak, dan itu adalah 5.

glglgl
sumber
6

Dalam C semua string literal benar-benar array karakter, termasuk null-terminator.

Namun, terminator nol tidak dihitung dalam panjang string (literal atau tidak), dan itu tidak dicetak. Pencetakan berhenti ketika terminator nol ditemukan.

Beberapa programmer Bung
sumber
Apakah ada cara untuk memverifikasi ini tanpa menyimpan string dalam array?
Ajay Mishra
1
@AjayMishra Yah string sudah ada dalam array (seperti yang disebutkan) ... Tetapi jika tidak ada terminator nol maka printfakan keluar dari batas-batas string, dan mencetak karakter "acak" atau "sampah", dan mengembalikan sebuah nomor berbeda dari panjang tali. Jika Anda sudah tahu panjang string Anda juga bisa memeriksa apakah karakter pada indeks itu adalah '\0', yang akan berfungsi tetapi secara teknis tidak didefinisikan perilaku jika ukuran array tidak termasuk terminator (seperti pada char arr[5] = "hello";, yang tidak akan menambahkan terminator ke array).
Beberapa programmer Bung
@AjayMishra Ya E. g., Anda dapat melakukan char * p = "Hello"; int i = 0; while (p[i] != '\0') { printf("%d: %c", i, p[i]); i++; }dan melihat cara kerjanya: ini menunjukkan garis dengan indeks dan konten di baris itu. Setelah indeks 4, ia menemukan karakter 0 dan memecah loop while. Di sana Anda melihat bahwa ada 0 karakter.
glglgl
6

Semua jawaban benar-benar baik tetapi saya ingin menambahkan contoh lain untuk melengkapi semua ini

#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;
}

Bagi mereka yang tidak ingin mencoba ini di gdb online, hasilnya adalah:

Halo Dunia

Neraka

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

Apakah ini membantu untuk memahami apa yang dilakukan terminator melarikan diri? Ini bukan batas untuk array char atau string. Itu karakter yang akan mengatakan kepada pria yang mem-parsing-STOP, (cetak) parse sampai di sini.

PS: Dan jika Anda menguraikan dan mencetaknya sebagai array char

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

Anda mendapatkan:

Dunia neraka

di mana, spasi putih setelah l ganda, adalah terminator nol, namun, parsing array char, akan hanya nilai char dari setiap byte. Jika Anda melakukan parse lain dan mencetak nilai int setiap byte ("% d%, char_array [i]), Anda akan melihat bahwa (Anda mendapatkan representasi kode-ASCII) spasi putih memiliki nilai 0.

Tsakiroglou Fotis
sumber
4

Dalam Cfungsi printf()mengembalikan jumlah karakter yang dicetak, \0adalah nullterminator yang digunakan untuk menunjukkan akhir string dalam bahasa c dan tidak ada stringtipe c++bawaan pada , namun ukuran array Anda harus setidaknya lebih besar dari jumlah yang charAnda inginkan menyimpan.

Inilah refnya: cpp ref printf ()

beberapa pengguna
sumber
3

Tetapi bagaimana jika saya ingin mencetak string, katakan printf ("halo") walaupun saya telah menemukan bahwa itu tidak berakhir dengan \ 0 dengan mengikuti pernyataan

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

Output: 5

Anda salah. Pernyataan ini tidak mengkonfirmasi bahwa string literal "hello"tidak berakhir dengan karakter nol penghentian '\0'. Pernyataan ini mengonfirmasi bahwa fungsi printfmenampilkan elemen string hingga karakter nol terminasi ditemukan.

Ketika Anda menggunakan string literal seperti dalam pernyataan di atas maka kompiler membuat array karakter dengan durasi penyimpanan statis yang berisi elemen string string.

Jadi sebenarnya ungkapan ini

printf("hello")

diproses oleh kompiler sesuatu seperti yang berikut ini

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

Tindakan fungsi printf dalam hal ini dapat Anda bayangkan dengan cara berikut

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

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

    return result;
}

Untuk mendapatkan jumlah karakter yang tersimpan dalam string literal "halo" Anda dapat menjalankan program berikut

#include <stdio.h>

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

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

    return 0;
}

Output program adalah

The size of the literal "hello" is 6
Vlad dari Moskow
sumber
0

Anda harus menghapus konsep Anda terlebih dahulu .. Karena akan dihapus ketika Anda berurusan dengan array, Perintah cetak yang Anda gunakan hanya menghitung karakter yang ditempatkan dalam paranthesis. Diperlukan dalam string array yang akan diakhiri dengan \ 0

Muhammad Kashif
sumber
0

String adalah vektor karakter. Berisi urutan karakter yang membentuk string, diikuti oleh string karakter akhir khusus: '\ 0'

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

Contoh: vektor karakter berikut bukan satu string karena tidak diakhiri dengan '\ 0'

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

Nicola Brogelli
sumber
Tidak ada vektor di C, saya kira.
Ajay Mishra