Saya membaca beberapa kode emulator dan saya telah membalas sesuatu yang sangat aneh:
switch (reg){
case 'eax':
/* and so on*/
}
Bagaimana ini mungkin? Saya pikir Anda hanya bisa switch
pada tipe integral. Apakah ada beberapa tipuan makro yang sedang terjadi?
c
switch-statement
label
constants
Ian Colton
sumber
sumber
'eax'
dan itu menghitung nilai integer konstanint
, jadi legal. Namun, nilai konstanta multi-karakter ditentukan oleh implementasi, jadi kode mungkin tidak berfungsi seperti yang diharapkan pada compiler lain. Sebagai contoh,eax
mungkin0x65
,0x656178
,0x65617800
,0x786165
,0x6165
, atau sesuatu yang lain.'eax' != 'ebx'
, tentu saja, itu hanya gagal satu atau dua contoh Anda. Meskipun mungkin ada beberapa kode di suatu tempat yang berlaku*(int*)("eax") == 'eax'
, dan karena itu gagal sebagian besar contoh Anda.'eax'
mungkin membandingkan sama dengan'ebx'
atau dengan'ax'
, dan pernyataan sakelar tidak akan berfungsi sebagaimana mestinya.Jawaban:
(Hanya Anda yang dapat menjawab bagian "tipuan makro" - kecuali jika Anda menempelkan lebih banyak kode. Tapi tidak banyak yang bisa dilakukan makro di sini - secara formal Anda tidak diizinkan untuk mendefinisikan ulang kata kunci ; perilaku dalam melakukan itu tidak ditentukan.)
Untuk mencapai keterbacaan program, pengembang yang cerdas mengeksploitasi perilaku implementasi yang ditentukan .
'eax'
adalah tidak string, tapi multi-karakter konstan . Perhatikan dengan cermat karakter kutipan tunggal di sekitareax
. Kemungkinan besar itu memberi Andaint
dalam kasus Anda yang unik untuk kombinasi karakter itu. (Seringkali setiap karakter menempati 8 bit dalam 32 bitint
). Dan semua orang tahu Anda bisaswitch
diint
!Terakhir, referensi standar:
Standar C99 mengatakan:
sumber
'ab'
dari'a'
dan'b'
.Menurut Standar C (6.8.4.2 Pernyataan sakelar)
dan (6.6 Ekspresi konstan)
Sekarang apa
'eax'
?Standar C (6.4.4.4 Konstanta karakter)
Jadi
'eax'
adalah konstanta karakter integer sesuai dengan paragraf 10 dari bagian yang samaJadi menurut kutipan yang disebutkan pertama itu bisa menjadi operan dari ekspresi konstan integer yang dapat digunakan sebagai label kasus.
Perhatikan bahwa konstanta karakter (diapit tanda kutip tunggal) memiliki tipe
int
dan tidak sama dengan string literal (urutan karakter yang diapit tanda kutip ganda) yang memiliki tipe larik karakter.sumber
Seperti yang dikatakan orang lain, ini adalah
int
konstanta dan nilai aktualnya ditentukan oleh implementasi.Saya berasumsi sisa kode terlihat seperti ini
Bisa dipastikan bahwa 'eax' di bagian pertama memiliki nilai yang sama dengan 'eax' di bagian kedua, jadi semuanya berhasil, bukan? ... salah.
Dalam komentar @Davislor mencantumkan beberapa kemungkinan nilai untuk 'eax':
Perhatikan nilai potensial pertama? Artinya
'e'
, mengabaikan dua karakter lainnya. Masalahnya adalah program mungkin menggunakan'eax'
,'ebx'
dan sebagainya. Jika semua konstanta ini memiliki nilai yang sama dengan yang'e'
Anda hasilkanIni tidak terlihat terlalu bagus, bukan?
Bagian yang baik tentang "implementasi-didefinisikan" adalah bahwa pemrogram dapat memeriksa dokumentasi kompilator mereka dan melihat apakah ia melakukan sesuatu yang masuk akal dengan konstanta ini. Jika ya, rumah gratis.
Bagian buruknya adalah bahwa beberapa orang malang lainnya dapat mengambil kode dan mencoba mengkompilasinya menggunakan kompiler lain. Kesalahan kompilasi instan. Program ini tidak portabel.
Seperti yang ditunjukkan @zwol di komentar, situasinya tidak seburuk yang saya kira, dalam kasus buruk kode tidak dapat dikompilasi. Ini setidaknya akan memberi Anda nama file dan nomor baris yang tepat untuk masalah tersebut. Namun, Anda tidak akan memiliki program yang berfungsi.
sumber
assert('eax' != 'ebx'); //if this fails you can't compile the code because...
apakah ada sesuatu yang dapat dilakukan oleh penulis asli untuk mencegah kegagalan kompiler lain tanpa mengganti konstruksi seluruhnya>Fragmen kode menggunakan keanehan historis yang disebut konstanta karakter multi-karakter , juga disebut sebagai multi-karakter .
'eax'
adalah konstanta integer yang nilainya ditentukan oleh implementasi.Berikut adalah halaman yang menarik tentang multi-karakter dan bagaimana mereka dapat digunakan tetapi tidak seharusnya:
http://www.zipcon.net/~swhite/docs/computers/languages/c_multi-char_const.html
Melihat jauh ke belakang ke kaca spion, berikut adalah bagaimana manual C asli oleh Dennis Ritchie dari masa lalu yang baik ( https://www.bell-labs.com/usr/dmr/www/cman.pdf ) menentukan konstanta karakter .
Frasa terakhir adalah semua yang perlu Anda ingat tentang konstruksi aneh ini: Konstanta karakter dengan lebih dari satu karakter secara inheren bergantung pada mesin dan harus dihindari.
sumber