Apakah perlu untuk mengikuti standar, mengambil standar C dalam hal ini?

17

Ada beberapa orang yang sangat berpengalaman di Stack Overflow yang selalu berbicara tentang standar C. Orang-orang tampaknya tidak menyukai solusi non-portabel, bahkan jika mereka bekerja untuk saya. Ok, saya mengerti bahwa standar perlu diikuti, tetapi tidakkah hal itu menghambat kreativitas programmer?

Apa manfaat konkret yang berasal dari mengikuti standar? Terutama karena penyusun dapat menerapkan standar sedikit berbeda.

0decimal0
sumber
7
Bisakah Anda mengklarifikasi apa yang Anda maksud dengan "standar"? Apakah maksud Anda tidak bersikap pada perilaku yang tidak ditentukan oleh standar? Atau tidak menggunakan ekstensi / fitur kompiler? Atau konvensi gaya?
ikh
1
@ Sheikh Dia mengambil tentang standar ISO C (C90, C99, C11).
Aseem Bansal
9
Itu sama dengan mengatakan bahwa menulis atau berbicara dalam bahasa Inggris, menggunakan tata bahasa dan kosakata bahasa Inggris, membuat belenggu kreativitas Anda. Tentu, orang dapat melakukan hal-hal indah dengan melanggar aturan, dengan biaya koherensi, tetapi Anda dapat menulis jutaan buku kreatif sambil tetap mengikuti "standar" bahasa Inggris.
Avner Shahar-Kashtan
dapatkah Anda menambahkan contoh "Orang-orang tampaknya tidak menyukai solusi non-portabel, bahkan jika mereka bekerja untuk saya"?
BЈовић
1
@ PHIfounder Hanya untuk mengatasi kasus terakhir itu, Anda dapat menghilangkan kembalinya dari utama, secara implisit mengembalikan 0 :)
Daniel Gratzer

Jawaban:

45

Ada beberapa alasan mengapa berpegang teguh pada standar adalah hal yang baik.

  1. Terkunci dalam kompiler sangat menyebalkan. Anda sepenuhnya berada di bawah kekuasaan sekelompok pengembang dengan agenda mereka sendiri. Mereka jelas tidak keluar untuk mendapatkan Anda atau apa pun, tetapi jika kompiler Anda mulai tertinggal pada optimasi, fitur baru, perbaikan keamanan dll, terlalu buruk; Anda terjebak. Dalam kasus-kasus ekstrem, beberapa perusahaan harus mulai menambal alat apa pun yang telah mereka andalkan. Ini sangat membuang-buang uang dan waktu ketika ada alat kerja lain di luar sana.

  2. Terkunci ke dalam platform lebih sulit. Jika Anda mendorong perangkat lunak di Linux dan ingin beralih ke Windows karena Anda menyadari pasar Anda benar-benar ada, Anda akan bersenang-senang mengubah setiap peretasan non-portabel yang Anda miliki dalam kode Anda untuk bermain bagus dengan GCC dan MSVC. Jika Anda memiliki beberapa desain inti yang didasarkan pada sesuatu seperti itu, semoga berhasil!

  3. Perubahan yang tidak kompatibel mundur menyebalkan yang paling sulit. Standar tidak akan pernah memecahkan kode Anda (Abaikan python). Beberapa penulis kompiler acak mungkin memutuskan bahwa benar-benar tambahan khusus implementasi ini tidak sepadan dengan masalah dan menjatuhkannya. Jika Anda mengandalkannya, maka Anda terjebak pada versi lama apa pun yang terakhir digunakan.

Jadi pesan utama di sini, berpegang teguh pada standar membuat Anda lebih fleksibel . Anda memiliki bahasa yang lebih terbatas, tetapi Anda memiliki lebih banyak

  • Perpustakaan
  • Dukungan (orang-orang tahu standarnya, tidak setiap peretas khusus kompiler yang rumit)
  • Platform yang tersedia
  • Alat dewasa
  • Keamanan (bukti masa depan)

Ini keseimbangan yang halus, tetapi mengabaikan standar sama sekali merupakan kesalahan. Saya cenderung mengatur kode C saya untuk mengandalkan abstraksi yang dapat diimplementasikan dengan cara yang tidak portabel, tetapi saya bisa porting secara transparan tanpa mengubah semua yang bergantung pada abstraksi.

Daniel Gratzer
sumber
+1 cukup adil :), terima kasih ... Saya benar-benar bingung cara penyusun sedikit menyimpang dari standar dan membuat saya merasa skeptis tentang mengikutinya secara ketat, perlu mengetahui pro dan kontra dari itu dan Anda dengan jelas mengidentifikasi mereka.
0decimal0
6
Perilaku yang tidak terdefinisi mungkin menyebalkan juga. Dengan c, cukup mudah menjelajah ke UB jika Anda tidak mengikuti standar dengan cermat.
CodesInChaos
@CodesInChaos Setuju, perilaku tidak terdefinisi bagus di satu sisi karena memungkinkan untuk beberapa optimisasi gila, tetapi di sisi lain debugging itu ...
Daniel Gratzer
6

Standar adalah semacam "kontrak" antara Anda dan kompiler Anda yang mendefinisikan arti dari program Anda. Sebagai programmer, kita sering memiliki model mental tertentu tentang bagaimana bahasa bekerja, dan model mental ini sering bertentangan dengan standar. (Sebagai contoh, programmer C sering menganggap pointer sebagai kira-kira "integer yang menunjukkan alamat memori", dan oleh karena itu menganggap bahwa aman untuk melakukan aritmatika / konversi / manipulasi pada pointer yang mungkin dilakukan dengan integer yang menunjukkan memori address. Asumsi ini tidak sesuai dengan standar; itu sebenarnya memberlakukan batasan yang sangat ketat pada apa yang dapat Anda lakukan dengan pointer.)

Jadi, apa keuntungan mengikuti standar, daripada model mental Anda sendiri?

Sederhananya, standarnya benar, dan model mental Anda sendiri salah. Model mental Anda biasanya adalah pandangan yang disederhanakan tentang bagaimana segala sesuatu bekerja pada sistem Anda sendiri, dalam kasus umum, dengan semua optimisasi kompiler dinonaktifkan; vendor compiler umumnya tidak berupaya untuk menyesuaikan diri dengannya, terutama ketika menyangkut optimasi. (Jika Anda tidak memegang akhir kontrak Anda, Anda tidak dapat mengharapkan perilaku spesifik dari kompiler: sampah masuk, sampah keluar.)

Orang-orang tampaknya tidak menyukai solusi non-portabel, bahkan jika mereka bekerja untuk saya.

Mungkin lebih baik untuk mengatakan, "bahkan jika mereka tampaknya bekerja untuk saya". Kecuali jika kompiler Anda secara khusus mendokumentasikan bahwa perilaku yang diberikan akan berfungsi (yaitu: kecuali jika Anda menggunakan standar yang diperkaya, yang terdiri dari dokumentasi yang tepat ditambah kompiler), Anda tidak tahu itu benar-benar berfungsi, atau bahwa itu benar-benar dapat diandalkan. Sebagai contoh, integer overflow yang ditandatangani biasanya menghasilkan pembungkus pada banyak sistem (jadi, INT_MAX+1biasanya INT_MIN) - kecuali bahwa kompiler "tahu" bahwa aritmatika integer yang ditandatangani tidak pernah meluap dalam program C (benar), dan sering melakukan optimasi yang sangat mengejutkan berdasarkan ini " pengetahuan".

ruakh
sumber
1
Anda dapat mengkompilasi -fwrapv, dan kemudian Anda menggunakan bahasa yang sedikit berbeda, non-standar di mana aritmatika integer yang ditandatangani selalu ditutup.
user253751
@immibis: Ketika C89 ditulis, menurut dokumen rasionalnya, mayoritas kompiler kontemporer mendefinisikan semantik pembungkus diam untuk integer overflow. Dalam banyak kasus, memiliki beberapa jenis jaminan tentang apa yang terjadi dalam kasus bilangan bulat bilangan bulat dapat memungkinkan kode menjadi lebih efisien daripada yang mungkin tanpa jaminan tersebut, terutama jika jaminan tersebut tidak sejauh yang mengharuskan perilaku pembungkusan yang tepat [tepat perilaku pembungkus dapat ditiru menggunakan matematika yang tidak ditandatangani, tetapi semantik yang lebih longgar tetapi masih memadai untuk memenuhi persyaratan dapat memungkinkan kode yang lebih efisien].
supercat
@immibis: Sayang sekali revisionis mampu meyakinkan orang bahwa perilaku yang diterapkan hampir dengan suara bulat di antara penyusun untuk platform tertentu (atau dalam beberapa kasus 100% dengan suara bulat) tidak pernah menjadi "standar" pada platform tersebut, karena dalam banyak kasus kehilangan efisiensi yang dihasilkan dari keharusan menghindari perilaku seperti itu tidak akan dapat dikembalikan oleh "optimasi" apa pun yang dapat dicapai oleh kompiler dengan mencabutnya.
supercat
4

Saya mengerti bahwa standar perlu diikuti, tetapi tidakkah hal itu membatasi kreativitas programmer? masih ada beberapa perbedaan dalam cara kompiler yang berbeda mengikuti standar. Misalnya saya dapat menulis kode yang berfungsi, sangat baik dalam kinerja dan kecepatan yaitu, semua yang penting, tetapi masih yang mungkin tidak sepenuhnya mengikuti standar.

Tidak. Standar ini memberi tahu apa yang diizinkan untuk dilakukan. Jika tidak ditentukan, Anda berada di wilayah perilaku yang tidak ditentukan, dan kemudian semua taruhan dibatalkan - program bebas untuk melakukan apa pun.


Karena Anda menyebutkan contoh spesifik void main()vs int main(), saya dapat meningkatkan jawaban saya.

void main()bukan deklarasi standar fungsi utama. Mungkin bekerja pada beberapa kompiler melalui ekstensi, tetapi bergantung pada implementasinya. Bahkan jika itu berhasil, Anda harus memeriksa apakah itu melakukan apa yang Anda inginkan. Masalahnya adalah, pengembang kompiler dapat memutuskan untuk menghapus void main()dengan rilis kompiler berikutnya, merusak aplikasi Anda.

Di sisi lain, standar dengan jelas mendefinisikan tanda tangan utama sebagai int main()dan memberitahu apa yang harus dilakukan.


Di sisi lain, ada hal-hal yang tidak didefinisikan dalam standar. Kemudian, standar lain mungkin berlaku (seperti misalnya, POSIX). Contoh terbaik mungkin dengan implementasi thread di c ++ 03, karena c ++ 03 program standar 1-threaded. Dalam hal ini, Anda dipaksa untuk menggunakan pustaka yang tergantung platform, atau sesuatu seperti boost .

BЈовић
sumber
4
Segala sesuatu yang dilakukan oleh kompiler yang bukan standar bukan perilaku yang tidak ditentukan, ekstensi kompiler didefinisikan dengan baik dalam arti bahwa mereka adalah deterministik dan disengaja. UB tidak.
Daniel Gratzer
@jozefg Cara ditanya - jelas bahwa OP memikirkan cara penerapan UB. Sebagai contoh, utas tidak didefinisikan dalam c ++ 03.
BЈовић
1
@deworde: Komentar dihapus dari jawabannya.
Kevin
@ jozefg Jika kompilator tertentu selalu membungkus bilangan bulat yang ditandatangani, itu dapat dianggap sebagai ekstensi bahasa tidak berdokumen. (Tentu saja, tidak berdokumen berarti Anda tidak memiliki jaminan tentang mereka tidak menghapus ekstensi)
user253751
-6

Jangan ikuti aturan JIKA proyek Anda tentang proyek khusus, misalnya proyek pemerintah atau tentara, tetapi Anda harus mengikuti aturan JIKA Anda berbicara tentang sumber terbuka atau proyek besar dengan tim yang didistribusikan.

Uknown
sumber
2
tanpa penjelasan, jawaban ini dapat menjadi sia-sia jika ada orang yang memposting pendapat yang berbeda. Misalnya, jika seseorang memposting klaim seperti "ikuti aturan JIKA proyek Anda adalah tentang proyek khusus, misalnya proyek pemerintah atau tentara, tetapi Anda tidak perlu mengikuti aturan JIKA Anda berbicara tentang sumber terbuka ..." , bagaimana jawaban ini membantu pembaca untuk memilih dua pendapat yang bertentangan? Pertimbangkan untuk mengeditnya menjadi bentuk yang lebih baik
agas
2
Uknown: Anda akan terkejut mengetahui berapa banyak standar yang ada dalam proyek pemerintah ...
Deer Hunter