Bagaimana komputer membedakan '\ 0' (karakter nol) dari “unsigned int = 0”?

29

Jika dalam situasi tertentu, Anda memiliki array karakter (diakhiri tentu saja dengan karakter nol) dan tepat setelah itu, di posisi berikutnya dalam memori, Anda ingin menyimpan 0sebagai int yang tidak ditandatangani, bagaimana komputer membedakannya? dua?

Angelixus
sumber
18
Anda bertanya tentang komputer biasa yang jawabannya benar. Namun, dulu ada beberapa arsitektur yang menggunakan memori yang ditandai untuk membedakan antara tipe data.
grawity
12
Cara yang sama komputer tidak dapat membedakan float 4 byte dari integer 4 byte (merepresentasikan angka yang sangat berbeda).
Hagen von Eitzen
6
Meskipun mengakhiri string dengan 0x00 adalah umum, ada bahasa yang menggunakan string awalan panjang. Satu atau dua byte pertama akan berisi jumlah byte dalam string. Dengan cara ini, 0x00 pada akhirnya tidak diperlukan. Saya ingat Pascal dan BASIC melakukan itu. Mungkin COBOL juga.
lit
@lit juga memformat tajuk dalam banyak protokol komunikasi. "Halo saya pesan seperti ini dan saya panjangnya byte ini". Seringkali karena Anda perlu menyimpan tipe data yang kompleks di dalamnya, maka terminasi nol menjadi lebih sulit untuk diurai.
mathreadler
1
@lit: Sebagian besar varian Pascal dan BASIC ya, dan PL / I dan Ada - dan di Jawa sejak pembagian substring dijatuhkan dalam 7u6 secara efektif menggunakan awalan panjang array - tetapi COBOL hanya mengurutkan: Anda dapat membaca data dari pic X occurs m to n depending on v( dan hitungannya bisa di mana saja, tidak hanya sesaat sebelumnya), tetapi menyimpannya lebih rumit.
dave_thompson_085

Jawaban:

86

Tidak.

Terminator string adalah byte yang berisi semua 0 bit.

Int unsigned adalah dua atau empat byte (tergantung pada lingkungan Anda) masing-masing berisi semua 0 bit.

Dua item disimpan di alamat yang berbeda. Kode yang dikompilasi Anda melakukan operasi yang cocok untuk string di lokasi sebelumnya, dan operasi yang cocok untuk nomor biner yang tidak ditandatangani di yang terakhir. (Kecuali jika Anda memiliki bug dalam kode Anda, atau kode pintar yang berbahaya!)

Tetapi semua byte ini terlihat sama dengan CPU. Data dalam memori (dalam arsitektur set instruksi yang paling umum) tidak memiliki tipe apa pun yang terkait dengannya. Itu adalah abstraksi yang hanya ada dalam kode sumber dan berarti sesuatu hanya untuk kompiler.

Sunting-ditambahkan: Sebagai contoh: Sangat mungkin, bahkan umum, untuk melakukan aritmatika pada byte yang membentuk string. Jika Anda memiliki string karakter ASCII 8-bit, Anda dapat mengubah huruf dalam string antara huruf besar dan kecil dengan menambahkan atau mengurangi 32 (desimal). Atau jika Anda menerjemahkan ke kode karakter lain, Anda dapat menggunakan nilainya sebagai indeks ke dalam array yang unsur-unsurnya menyediakan bit coding yang setara dalam kode lainnya.

Untuk CPU karakternya adalah integer ekstra pendek. (masing-masing delapan bit, bukan 16, 32, atau 64.) Bagi kami manusia, nilainya dikaitkan dengan karakter yang dapat dibaca, tetapi CPU tidak tahu akan hal itu. Ia juga tidak tahu apa-apa tentang konvensi "C" dari "null byte mengakhiri sebuah string", baik (dan seperti yang banyak dicatat dalam jawaban dan komentar lain, ada lingkungan pemrograman di mana konvensi itu tidak digunakan sama sekali) .

Yang pasti, ada beberapa instruksi dalam x86 / x64 yang cenderung banyak digunakan dengan string - awalan REP, misalnya - tetapi Anda bisa menggunakannya pada array bilangan bulat, jika mereka mencapai hasil yang diinginkan.

Jamie Hanrahan
sumber
14
Itu sebabnya pengembang harus berhati-hati dengan string. Jika Anda memiliki, katakanlah, 100 byte berturut-turut, Anda dapat memuat paling banyak 99 karakter 1-byte di sana plus terminator pada byte terakhir. Jika Anda menulis string 100-byte di sana, program tidak akan dapat mengetahui bahwa string berakhir di sana dan akan terus membaca byte berturut-turut sampai nol byte secara kebetulan. Jika string lebih dari 100 byte, itu akan menimpa beberapa data yang berdekatan. Bahasa pemrograman tingkat tinggi (Java, C #, JS, dll.) Mengurus hal ini sendiri, tetapi dalam bahasa tingkat rendah seperti C, C ++, perakitan itu adalah tanggung jawab dev.
gronostaj
18
@ gronostaj Komentar Anda sedikit membingungkan: Tidak seperti dalam C, string C ++ juga menangani hal ini secara otomatis. C ++ juga umumnya tidak diklasifikasikan sebagai bahasa tingkat rendah (dan bahkan C terkadang tidak).
Konrad Rudolph
5
Ada (lama) arsitektur CPU yang memiliki penanda tipe pada nilai data, jadi mendereferensi integer sebagai pointer akan memberikan pengecualian.
Simon Richter
8
@JamieHanrahan Prosesor IA64 memiliki sedikit yang disebut NaT (atau "Bukan Hal") yang dapat melempar pengecualian jika nilai telah ditetapkan.
ErikF
4
@KonradRudolph "otomatis" tidak berarti "sangat mudah", tentu saja tidak di C ++
rackandboneman
5

Singkatnya tidak ada perbedaan (kecuali bahwa int adalah 2 atau 4 byte lebar dan karakter hanya 1).

Masalahnya adalah bahwa semua perpustakaan modern baik menggunakan teknik terminator nol atau menyimpan panjang string. Dan dalam kedua kasus program / komputer tahu itu mencapai akhir string ketika itu membaca karakter nol atau telah membaca karakter sebanyak ukurannya.

Masalah dengan ini mulai ketika terminator nol hilang atau panjangnya salah saat program mulai membaca dari memori tidak seharusnya.

BrainStone
sumber
3
Oh, ada perbedaan singkat - sebenarnya, pendek agak terkenal karena tipe data yang sangat bergantung pada mesin :)
rackandboneman
2

Tidak ada perbedaan. Kode mesin (assembler) tidak memiliki tipe variabel, melainkan tipe data ditentukan oleh instruksi.

Contoh yang lebih baik adalah intdan float, jika Anda memiliki 4 byte dalam memori, tidak ada info apakah itu sebuah intatau float(atau sesuatu yang lain sama sekali), namun ada 2 instruksi berbeda untuk penambahan integer dan penambahan float, jadi jika penambahan integer instruksi digunakan pada data, maka itu adalah bilangan bulat, dan sebaliknya.

Sama dengan string, jika Anda memiliki kode yang, katakanlah, melihat alamat dan menghitung byte hingga mencapai \0byte, Anda dapat menganggapnya sebagai fungsi yang menghitung panjang string.

Tentu saja pemrograman seperti ini akan menjadi kegilaan total, jadi itu sebabnya kami memiliki bahasa tingkat yang lebih tinggi yang dikompilasi ke kode mesin dan hampir tidak ada program di assembler secara langsung.

kajacx
sumber
2

Jawaban satu kata ilmiah adalah: metadata.

Metadata memberi tahu komputer apakah beberapa data di lokasi tertentu adalah int, string, kode program, atau apa pun. Metadata ini dapat menjadi bagian dari Kode program (seperti yang disebutkan Jamie Hanrahan) atau dapat secara eksplisit disimpan di suatu tempat.

CPU modern sering dapat membedakan wilayah memori yang ditetapkan untuk kode program dan wilayah data (misalnya, NX Bit https://en.wikipedia.org/wiki/NX_bit ). Beberapa perangkat keras eksotis juga dapat membedakan antara string dan angka, ya. Tetapi kasus yang biasa terjadi adalah bahwa Perangkat Lunak menangani masalah ini, baik melalui metadata implisit (dalam kode) atau metadata eksplisit (VM berorientasi objek sering menyimpan metadata (informasi jenis / kelas) sebagai bagian dari data (objek)) .

Keuntungan dari tidak membedakan antara berbagai jenis data adalah bahwa beberapa operasi menjadi sangat sederhana. Subsistem I / O tidak perlu mengetahui apakah data yang baru saja dibaca atau ditulisnya ke disk sebenarnya adalah kode program, teks atau angka yang dapat dibaca manusia. Itu semua hanya bit yang bisa diangkut melalui mesin. Biarkan kode program menangani masalah pengetikan mewah.

Klaw
sumber
0

Tidak. Anda melakukannya!

Atau kompiler / juru bahasa Anda.

Jika instruksi memberitahu komputer untuk menambahkan 0sebagai angka, itu akan melakukannya. Jika mereka memberitahu komputer untuk berhenti mencetak data setelah mencapai 0, sebagai ' \0'char, itu akan melakukannya.

Bahasa memiliki mekanisme untuk memastikan bagaimana memperlakukan data. Dalam variabel C ada tipe, suka int, floatdan char, dan kompiler menghasilkan instruksi yang tepat untuk setiap tipe data. Tapi C memungkinkan Anda melemparkan data dari suatu variabel ke variabel lain dari tipe yang berbeda, bahkan sebuah penunjuk dapat digunakan sebagai angka. Ke komputer itu semua bit seperti yang lain.

carlos prado
sumber
0

Karakter nol adalah satu byte dan int unsigned adalah dua byte.

Quentin 2
sumber