Apa arti casting?

18

Ketika pengkodean dalam bahasa tingkat rendah seperti CI menemukan bahwa casting kadang-kadang berarti 'menafsirkan kembali byte ini seolah-olah selalu dari tipe lain ini' dan di waktu lain sebagai 'mengubah nilai ini secara cerdas ke tipe lain ini'.

Apa arti asli dari kata itu dan apakah ada konsistensi kapan harus mengharapkan konversi dan kapan harus mengharapkan penafsiran ulang mentah?

Alexander Torstling
sumber
apa yang ada di artikel Wikipedia yang tidak Anda mengerti? " konversi tipe , typecasting , dan paksaan adalah cara yang berbeda, secara implisit atau eksplisit, mengubah entitas dari satu tipe data menjadi yang lain ... Setiap bahasa pemrograman memiliki aturan sendiri tentang bagaimana jenis dapat dikonversi ..."
agas
Arti asli "untuk melemparkan" tidak ada hubungannya dengan pemrograman, lihat di sini merriam-webster.com/dictionary/cast
Doc Brown
1
Lot (kebanyakan dari perspektif bahasa yang dikelola) di blog Eric Lippert dalam kategori operator pemain
AakashM
1
@gnat: Saya tidak yakin apakah itu pertanyaan serius atau hanya upaya trolling. Tetapi saya ingin tahu bagaimana cara mengetahui apa yang akan dilakukan oleh kompiler: mengonversi, membuat atau memaksa? Apa aturan mainnya?
Alexander Torstling
1
@DocBrown Saya pikir istilah castdalam arti komputasi lebih mirip dengan casting dalam arti metalurgi, di mana bentuk logam cair direformasi ketika dituangkan ke dalam cetakan: britannica.com/EBchecked/topic/377665/metallurgy/81884/Casting
KChaloux

Jawaban:

10

Casting dalam bahasa C itu unik, tidak seperti bahasa lain. Itu juga tidak pernah cerdas.

Casting dalam C mengkonversi nilai dari satu tipe ke tipe lainnya menggunakan aturan yang didefinisikan dengan cermat. Jika Anda benar-benar perlu tahu, baca standarnya. Kalau tidak, poin utamanya adalah:

  1. Konversi antara tipe integer mempertahankan nilai, jika memungkinkan. Jika tujuan memiliki lebih banyak bit, ini melebar dan umumnya aman, tetapi mungkin melibatkan ekstensi tanda. Jika lebih sempit, bit akan hilang.
  2. Konversi antara jenis pointer mempertahankan nilai pointer, tetapi hasilnya sering tidak terdefinisi, seringkali tidak portabel dan sering berguna untuk skenario lanjutan.
  3. Konversi antara tipe integer dan pointer OK jika integer cukup besar, dan mempertahankan pola bit (apa pun yang mungkin terjadi artinya). Jika bilangan bulat terlalu kecil, hasilnya tidak jelas tetapi tidak berguna. Sebagai aturan 'panjang' cukup lebar untuk 'void *', tetapi tidak ada jaminan! Pointer yang dibuat dengan cara ini mungkin tidak valid, dengan segala macam cara yang menarik.
  4. Konversi antara tipe float dan integer adalah konversi aritmatika sebagaimana didefinisikan oleh rutin pustaka yang sesuai (dengan pemotongan, bukan pembulatan).
  5. Anda dapat membuang nilai kembali fungsi untuk membatalkan. Saya tidak pernah. Tidak melakukan apa-apa.

Beberapa gips diterapkan secara implisit, dan dalam beberapa gips kompiler akan mengeluarkan peringatan. Yang terbaik untuk memperhatikan peringatan!

Definisi kamus untuk pemain paling baik diabaikan, karena tidak membantu. Banyak pemeran yang lebih baik dideskripsikan dengan istilah konversi atau pemaksaan, jadi perlu juga diketahui.

C ++ jauh lebih rumit, tetapi Anda tidak menanyakan itu, bukan?

david.pfx
sumber
Saya tertarik pada aturan praktis, dan bukan detail yang sangat kecil, tetapi saya tertarik pada bahasa lain selain C jika itu membantu menyelesaikan masalah.
Alexander Torstling
2
Apa yang saya berikan di sini adalah generik dan masuk akal. Untuk menulis kode C / C ++ profesional tingkat rendah, detail sangat kecil sangat penting. Sebagian besar bahasa tidak memiliki masalah seperti ini dalam konversi jenisnya. Maaf jika itu tidak menyelesaikan masalah Anda.
david.pfx
Kecuali bahwa mengkonversi dari dan T*ke void*belakang selalu didefinisikan dengan baik.
Miles Rout
@ Miles: Sebenarnya, mengubah T * ke U * dan kembali diperlukan untuk mempertahankan nilai pointer asli. Dalam jawaban saya, saya hanya mengatakan 'sering tidak didefinisikan' untuk membuatnya singkat, 'karena beberapa detailnya sangat berantakan.
david.pfx
1
@supercat: Lihat n1570 S6.3.2.3. Konversi / round-tripping antara T *, U * dan void * selalu mempertahankan nilai pointer hanya dengan satu pengecualian. Jika T * tidak disejajarkan dengan benar, itu adalah perilaku yang tidak terdefinisi. Saya menerima poin Anda, tetapi hanya sejauh itu.
david.pfx
2

Bagian dari kamus Webster ini memberikan definisi yang tepat:

a: untuk memberikan bentuk (zat) dengan menuangkan dalam bentuk cair atau plastik ke dalam cetakan dan membiarkan mengeras tanpa tekanan
b: untuk membentuk dengan proses ini

Jadi, sebelum casting, "objek" Anda (bukan secara harfiah objek OOP) dalam bentuk (tipe) tertentu. Ketika Anda melemparkannya kembali, itu adalah "tuangkan beton" di sekitarnya untuk membuatnya menjadi bentuk baru, itulah yang Anda lakukan dengan casting. Anda memiliki angka sebagai bilangan bulat berbentuk segi enam, dan setelah casting, Anda akan mendapatkan string berbentuk persegi panjang.

Juha Untinen
sumber
2
Juga : "Untuk menetapkan peran tertentu pada (aktor)".
Kelly Thomas
Ya. Saya yakin ini yang terbaik. +1.
david.pfx
2

Mungkin berguna untuk memisahkan gips C menjadi dua kelompok:

  1. Numeric casts - mengonversi angka antara satu representasi ke yang lain, berusaha mempertahankan nilainya. Misalnya - (int)3.1akan 3. Ada aturan pasti yang mendefinisikan apa yang terjadi ketika nilai pastinya tidak dapat disimpan.

  2. Cast Pointer - Menyimpan alamat memori, tetapi mengubah cara itu dereferenced. Misalnya, untuk float x=3.5, *(int *)&xakan memberikan 1080033280- bilangan bulat ini diwakili oleh pola bit yang sama yang mewakili float 3.5.

ugoren
sumber
Keep the memory address, but change the way it's dereferenced.Menereferensi pointer yang dihukum tidak ditentukan. Standar hanya menjamin pengecoran dari A *ke B *& kembali akan menghasilkan hal yang sama A *, yang mungkin tidak berlaku untuk dereferensi di tempat pertama - atau bahwa jika B *a char *, dapat digunakan untuk membaca representasi objek dari jenis apa pun. Untuk semua tipe lainnya, B *pointer dereferencing adalah type-punning, UB, & melanggar alias ketat. Pokoknya, bahkan jika kompilator tidak membuang contoh 2 di atas karena alasan itu, Anda membuat asumsi yang tidak dapat dipercaya tentang pola bit
underscore_d
1
cast (v): to receive form in a mold

Dalam C ++ berbagai jenis gips dapat dibuat lebih eksplisit, dengan reinterpret_cast arti "perlakukan byte ini seolah-olah mereka sudah hal lain ini". Dalam C, Anda dapat membuatnya benar-benar eksplisit dengan menggunakan union, casting dengan (type)operator akan berusaha untuk menjaga hasil yang setara secara numerik, hingga kehilangan presisi.

U2EF1
sumber
2
Dalam C pointer gips selalu diinterpretasikan ulang dan gips nilai selalu mempertahankan nilai sebaik mungkin. Di C ++ ada beberapa cara untuk melakukan pointer pointer, itulah sebabnya ada tipe cast yang lebih eksplisit.
Jan Hudec
Semantik pointer-cast belum tentu "menafsirkan kembali". Itu akan sah untuk prosesor yang menggunakan pengalamatan kata tetapi ingin berinteraksi dengan baik dengan kode berbasis byte untuk memiliki int*yang satu kata dan char*yang dua kata [dengan byte kedua memilih byte kata yang tinggi atau rendah]. Casting (int*)ke to (char*)akan membutuhkan penambahan kata tambahan yang harus berupa nilai berapa pun yang menentukan byte pertama dari int.
supercat