Apa sebenarnya aturan "seolah-olah" itu?

89

Seperti judulnya,

Apa sebenarnya aturan "seolah-olah" itu?

Jawaban khas yang akan didapat adalah:

Aturan yang memungkinkan setiap dan semua transformasi kode yang tidak mengubah perilaku program yang dapat diamati

Dari waktu ke waktu kami terus mendapatkan perilaku dari implementasi tertentu yang dikaitkan dengan aturan ini. Berkali-kali salah. Jadi, apa sebenarnya aturan ini. Standar tidak secara jelas menyebutkan aturan ini sebagai bagian atau paragraf, jadi apa sebenarnya yang termasuk dalam lingkup aturan ini? Bagi saya ini tampak seperti area abu-abu yang tidak didefinisikan secara rinci oleh standar. Bisakah seseorang menguraikan detail yang mengutip referensi dari standar?

Catatan: Memberi tag ini sebagai C dan C ++ keduanya, karena relevan dengan kedua bahasa.

Alok Save
sumber
2
Ini mengacu pada mesin abstrak.
Alexey Frunze
" Memberi tag ini sebagai C dan C ++, karena relevan dengan kedua bahasa " Ini relevan dalam bahasa apa pun.
penasaran
@AlexeyFrunze " Ini mengacu pada mesin abstrak " Ini mengacu pada keadaan "mesin abstrak" sebagai alat dan bukan tujuan, dan tidak relevan dalam hal penyesuaian, karena "abstrak" itulah alat spesifikasi yang tidak nyata.
penasaran

Jawaban:

98

Apa yang dimaksud dengan aturan " seolah-olah "?

Aturan " seolah-olah " pada dasarnya menentukan transformasi apa yang diizinkan untuk dilakukan implementasi pada program C ++ legal. Singkatnya, semua transformasi yang tidak mempengaruhi " perilaku yang dapat diamati " program (lihat di bawah untuk definisi yang tepat) diperbolehkan.

Tujuannya adalah memberikan kebebasan implementasi untuk melakukan pengoptimalan selama perilaku program tetap sesuai dengan semantik yang ditentukan oleh C ++ Standard dalam hal mesin abstrak.


Di mana Standar memperkenalkan aturan ini?

Standar C ++ 11 memperkenalkan aturan " seolah-olah " di Paragraf 1.9 / 1:

Deskripsi semantik dalam Standar Internasional ini mendefinisikan mesin abstrak nondeterministik berparameter. Standar Internasional ini tidak mensyaratkan struktur implementasi yang sesuai. Secara khusus, mereka tidak perlu menyalin atau meniru struktur mesin abstrak. Sebaliknya, implementasi yang sesuai diperlukan untuk meniru (hanya) perilaku yang dapat diamati dari mesin abstrak seperti yang dijelaskan di bawah ini.

Juga, catatan kaki penjelasan menambahkan:

Ketentuan ini kadang-kadang disebut aturan “seolah-olah” , karena dalam pelaksanaannya bebas mengabaikan setiap persyaratan Standar Internasional ini sepanjang persyaratan tersebut seolah-olah telah dipatuhi, sejauh dapat ditentukan dari perilaku yang dapat diamati. dari program. Misalnya, implementasi aktual tidak perlu mengevaluasi bagian dari ekspresi jika dapat menyimpulkan bahwa nilainya tidak digunakan dan tidak ada efek samping yang mempengaruhi perilaku program yang dapat diamati yang dihasilkan.


Apa yang diamanatkan oleh aturan itu?

Paragraf 1.9 / 5 lebih lanjut menentukan:

Implementasi yang sesuai dengan menjalankan program yang terbentuk dengan baik akan menghasilkan perilaku yang dapat diamati yang sama sebagai salah satu kemungkinan eksekusi dari instance yang sesuai dari mesin abstrak dengan program yang sama dan input yang sama . Namun, jika eksekusi semacam itu mengandung operasi yang tidak ditentukan, Standar Internasional ini tidak menempatkan persyaratan pada pelaksanaan yang menjalankan program tersebut dengan masukan tersebut (bahkan tidak berkaitan dengan operasi sebelum operasi yang tidak ditentukan pertama).

Perlu ditekankan bahwa batasan ini hanya berlaku ketika "menjalankan program yang dibentuk dengan baik" , dan bahwa kemungkinan hasil dari menjalankan program yang berisi perilaku yang tidak ditentukan tidak dibatasi. Ini dijelaskan dalam Paragraf 1.9 / 4 juga:

Operasi tertentu lainnya dijelaskan dalam Standar Internasional ini sebagai tidak terdefinisi (misalnya, efek dari mencoba memodifikasi objek const). [Catatan: Standar Internasional ini tidak memberlakukan persyaratan pada perilaku program yang mengandung perilaku tidak terdefinisi . —Kirim catatan]

Akhirnya, mengenai definisi " perilaku yang dapat diamati ", Paragraf 1.9 / 8 berbunyi sebagai berikut:

Persyaratan paling sedikit untuk implementasi yang sesuai adalah:

- Akses ke objek volatile dievaluasi secara ketat sesuai dengan aturan mesin abstrak.

- Pada penghentian program, semua data yang ditulis ke dalam file harus identik dengan salah satu kemungkinan hasil yang akan dihasilkan oleh eksekusi program sesuai dengan semantik abstrak.

- Dinamika input dan output dari perangkat interaktif harus berlangsung sedemikian rupa sehingga mendorong output benar-benar dikirimkan sebelum program menunggu input. Apa yang merupakan perangkat interaktif ditentukan oleh implementasi.

Ini secara kolektif disebut sebagai perilaku program yang dapat diamati . [ Catatan : Korespondensi yang lebih ketat antara semantik abstrak dan aktual dapat ditentukan oleh setiap implementasi. - catatan akhir ]


Apakah ada situasi di mana aturan ini tidak berlaku?

Sepengetahuan saya, satu-satunya pengecualian untuk aturan " seolah-olah " adalah menyalin / memindahkan elision, yang diizinkan meskipun salinan konstruktor, pemindah konstruktor, atau penghancur kelas memiliki efek samping. Kondisi yang tepat untuk ini ditentukan dalam Paragraf 12.8 / 31:

Ketika kriteria tertentu terpenuhi, implementasi diperbolehkan untuk menghilangkan salinan / memindahkan konstruksi objek kelas, bahkan jika konstruktor dipilih untuk operasi salin / pemindahan dan / atau destruktor untuk objek memiliki efek samping . [...]

Andy Prowl
sumber
2
Saya telah melihat kutipan ini. Yang tidak jelas adalah definisi perilaku yang dapat diamati. Apa sebenarnya yang memenuhi syarat sebagai perilaku yang dapat diamati? Salin elision menjadi pengecualian untuk aturan seolah-olah cukup terkenal dan sebenarnya bukan bagian dari pertanyaan saya.
Alok Hemat
2
@AlokSave: Dalam standar C, kita melihat "Mengakses objek yang mudah menguap, memodifikasi objek, memodifikasi file, atau memanggil fungsi yang melakukan salah satu dari operasi tersebut semuanya merupakan efek samping". Agaknya ada sesuatu yang setara dalam standar C ++. Secara informal, saya kira "apapun yang mengubah interaksinya dengan dunia luar".
Oliver Charlesworth
1
Setiap perilaku yang mengubah status mesin abstrak (jadi, sesuatu yang mengubah variabel yang diteruskan atau variabel global, atau membaca dan menulis ke perangkat I / O).
Mats Petersson
1
Apakah ini berarti bahwa menghapus pengulangan tak terbatas yang tidak melakukan apa-apa diperbolehkan, selama tidak ada yang dapat diamati terjadi sesudahnya?
Harold
5
Satu hal yang perlu diperhatikan secara khusus adalah bahwa ini hanya berlaku untuk program hukum . Apa pun yang memicu perilaku tidak terdefinisi secara eksplisit berada di luar cakupan apa pun.
vonbrand
15

Di C11 aturan tidak pernah disebut dengan nama itu. Namun C, seperti C ++, mendefinisikan perilaku dalam istilah mesin abstrak. Aturan as-if ada di C11 5.1.2.3p4 dan p6 :

  1. Di mesin abstrak, semua ekspresi dievaluasi seperti yang ditentukan oleh semantik. Implementasi aktual tidak perlu mengevaluasi bagian dari ekspresi jika dapat menyimpulkan bahwa nilainya tidak digunakan dan tidak ada efek samping yang diperlukan yang dihasilkan (termasuk yang disebabkan oleh pemanggilan fungsi atau mengakses objek volatil).

  2. [...]

  3. Persyaratan paling sedikit untuk implementasi yang sesuai adalah:

    • Akses ke volatileobjek dievaluasi secara ketat sesuai dengan aturan mesin abstrak.
    • Pada penghentian program, semua data yang ditulis ke dalam file harus identik dengan hasil yang akan dihasilkan oleh eksekusi program sesuai dengan semantik abstrak.
    • Dinamika masukan dan keluaran dari perangkat interaktif harus berlangsung seperti ditentukan dalam 7.21.3 . Maksud dari persyaratan ini adalah agar keluaran yang tidak buffer atau baris-buffered muncul secepat mungkin, untuk memastikan bahwa pesan prompt benar-benar muncul sebelum program menunggu masukan.

     

    Ini adalah perilaku program yang dapat diamati.

Antti Haapala
sumber
-1

Di C, C ++, Ada, Java, SML ... dalam bahasa pemrograman apa pun yang ditentukan dengan baik dengan mendeskripsikan (biasanya banyak kemungkinan, perilaku non-deterministik) dari suatu program (terkena serangkaian interaksi pada port I / O) , tidak ada aturan seolah-olah yang berbeda .

Contoh aturan berbeda adalah salah satu yang mengatakan bahwa pembagian dengan nol menimbulkan pengecualian (Ada, Caml) atau dereferensi nol menimbulkan pengecualian (Java). Anda dapat mengubah aturan untuk menentukan sesuatu yang lain dan Anda akan berakhir dengan bahasa yang berbeda (bahwa beberapa orang lebih suka menyebutnya "dialek" (*). Ada aturan yang berbeda untuk menentukan beberapa penggunaan yang berbeda dari bahasa pemrograman seperti yang berbeda Aturan tata bahasa mencakup beberapa konstruksi sintaksis.

(*) Dialek menurut beberapa ahli bahasa adalah bahasa dengan "tentara". dalam konteks itu, itu bisa berarti bahasa pemrograman tanpa komite dan industri editor kompiler tertentu.

Aturan seolah-olah bukanlah aturan yang berbeda ; itu tidak mencakup program apa pun secara khusus dan bahkan bukan aturan yang dapat didiskusikan, dihapus, atau diubah dengan cara apa pun : yang disebut "aturan" hanya menegaskan kembali bahwa semantik program ditentukan, dan hanya dapat dibawa-bawa (secara universal) didefinisikan, dalam hal interaksi yang terlihat dari pelaksanaan program dengan dunia "eksternal".

Dunia luar dapat berupa antarmuka I / O (stdio), GUI, bahkan penerjemah interaktif yang menghasilkan nilai yang dihasilkan dari bahasa aplikatif murni. Dalam C dan C ++ termasuk akses (yang ditentukan secara samar) ke objek volatile, yang merupakan cara lain untuk mengatakan bahwa beberapa objek pada titik tertentu harus direpresentasikan dalam memori secara ketat sesuai dengan ABI (Application Binary Interface) tanpa pernah menyebutkan ABI secara eksplisit.

Definisi dari apa yang disebut jejak eksekusi , juga disebut perilaku yang terlihat atau dapat diamati, mendefinisikan apa yang dimaksud dengan "aturan seolah-olah". Aturan seolah-olah mencoba menjelaskannya, tetapi dengan melakukannya, itu membingungkan orang lebih dari pada menjelaskan hal-hal karena memberikan ekspresi sebagai aturan semantik tambahan yang memberikan lebih banyak kelonggaran untuk implementasi.

Ringkasan:

  • Yang disebut "aturan seolah-olah" tidak melonggarkan batasan apa pun pada implementasi.
  • Anda tidak dapat menghapus aturan as-if dalam bahasa pemrograman apa pun yang ditentukan dalam istilah perilaku yang terlihat (jejak eksekusi yang disusun untuk interaksi dengan dunia luar) untuk mendapatkan dialek yang berbeda.
  • Anda tidak dapat menambahkan aturan seolah-olah ke bahasa pemrograman apa pun yang tidak ditentukan dalam perilaku yang terlihat.
penasaran
sumber
Jika orang percaya saya salah, dan ada "aturan seolah-olah" yang berbeda, mengapa mereka tidak mencoba mendeskripsikan varian dari C ++ (dialek) tanpa "aturan" itu? Apa arti spesifikasi C ++ tanpa itu? Sangat tidak mungkin untuk mengetahui apakah kompiler sudah sesuai. Atau bahkan untuk mendefinisikan penyesuaian.
penasaran