Selain kode mesin, tidak ada bahasa pemrograman yang mengeksekusi langsung pada perangkat keras, dalam arti bahwa Anda tidak dapat memberi makan teks sumber literal. Semua implementasi nyata harus menerjemahkan program sumber ke dalam bahasa "mesin".
Untuk beberapa implementasi, itu diterjemahkan secara statis. Kami biasanya menyebut implementasi ini "dikompilasi". Bagi yang lain, ini diterjemahkan ke dalam beberapa bentuk peralihan, yang kemudian diterjemahkan secara dinamis saat program dijalankan. Kami biasanya menyebut implementasi ini "ditafsirkan". Ada kontinum kemungkinan di antara ini, dan bahkan banyak CPU modern melakukan terjemahan dinamis sebagai bagian dari inti pelaksanaannya.
Bahkan ketika program Anda dikompilasi secara statis jauh sebelum eksekusi, kecuali jika Anda sedang menulis firmware, sangat jarang kode yang dikompilasi berjalan langsung pada bare metal tanpa ada yang mendukungnya. Sistem operasi menyediakan mesin virtual untuk program ruang-pengguna, seringkali menyediakan fitur seperti ilusi bahwa Anda memiliki CPU untuk diri sendiri. Ilusi ruang memori datar yang bisa lebih besar dari RAM fisik yang terpasang pada mesin bahkan disebut "memori virtual".
Di atas semua itu, bahkan ketika Anda sedang pemrograman di C, ada mesin virtual C! Secara tradisional disebut sebagai "runtime C", atau singkatnya CRT.
Karena C sebagian besar diterjemahkan langsung ke kode assembly / mesin jauh sebelumnya (pada beberapa platform, mungkin juga ada beberapa kode berulir , dan yang dapat dianggap sebagai bagian dari mesin virtual), mesin virtual biasanya hanya harus menangani startup dan menutup.
Startup biasanya melibatkan pengaturan stack dan heap; sistem operasi jarang menyediakan ini untuk Anda, dan merupakan tugas bahasa pemrograman untuk menyediakannya kepada programmer. Pada beberapa platform mungkin ada beberapa inisialisasi penanganan sinyal, pengaturan utas "utama" di lingkungan multi-utas, menjalankan konstruktor global jika program telah ditautkan ke kode C ++, menangani pustaka yang terhubung secara dinamis, atau ada mungkin diperlukan beberapa pemrosesan untuk mengatur argc / argv dan envp. Akhirnya, CRT mentransfer kontrol ke main.
Sedangkan untuk shutdown, banyak sistem operasi dapat mematikan proses secara tidak bersih, jadi shutdown tidak perlu melakukan banyak hal. Hal utama adalah untuk memproses panggilan atexit () untuk kasus di mana program keluar dengan bersih.