Panjang lama di c99
Dalam standar C99 yang mereka perkenalkan long long
. Apa tujuan dari ini? Dalam pengalaman pemrograman C saya (terbatas), saya hanya pernah melihat int 4-byte dan panjang 8-byte. Misalnya, dari Compiler Explorer:
Jika long
sudah 8
demikian, mengapa perlu ditambahkan long long
tipe lain ? Apa yang dilakukannya pada kompiler / arsitektur?
Jawaban
Jika panjang sudah 8 lalu, mengapa perlu ditambahkan lagi jenis panjang panjang? Apa yang dilakukannya pada kompiler / arsitektur?
"Jika panjang sudah 8" tidak selalu benar karena banyak kode yang bergantung pada 32-bit long
dan int
32 atau 16 bit.
Membutuhkan long
64-bit akan merusak basis kode. Ini adalah perhatian utama.
Namun membutuhkan long
untuk tetap 32-bit (dan tidak long long
) tidak akan membuat akses ke bilangan bulat 64-bit standar, oleh karena itu alasan untuk long long
.
Mengizinkan long
sebagai 32-bit atau 64-bit (atau lainnya) memungkinkan untuk transisi.
Berbagai fungsi masuk / kembali long
seperti fseek(), ftell()
. Mereka mendapat manfaat long
karena lebih dari 32-bit untuk dukungan file besar.
Praktik yang disarankan mendorong pemahaman yang lebih luas long
: "Jenis yang digunakan untuk size_t
dan ptrdiff_t
tidak boleh memiliki peringkat konversi bilangan bulat yang lebih besar dari itu signed long int
kecuali jika penerapannya mendukung objek yang cukup besar untuk membuatnya perlu." Ini terkait dengan ukuran memori yang melebihi 32-bit.
Mungkin di masa depan sebuah implementasi dapat menggunakan int/long/long long/intmax_t
32/64/128/256 bits.
IAC, saya melihat jenis lebar tetap intN_t
semakin populer selama long
dan long long
. Saya cenderung menggunakan fixed jenis lebar atau bool
, ( unsigned
) char
, int
/ unsigned
, size_t
, ( u
) intmax_t
dan cuti signed char
, ( unsigned
) short
, ( unsigned
) long
, ( unsigned
) long long
untuk kasus-kasus khusus.
Standar C hanya menjamin bahwa int
can menjadi (secara bebas) 2 byte, a long
can menjadi 4 byte, dan a long long
can menjadi 8 byte.
Nyatanya, MSVC tetap menggunakan 4 byte long
meski sudah 4 byte int
.
Satu-satunya persyaratan yang relevan untuk int
dan long
, dulu dan sekarang, adalah int
minimal harus 16 bit dan long
minimal 32 bit. Sistem 16- dan 32-bit keduanya cenderung memiliki 32-bit long
, dan mesin 64-bit jauh lebih jarang digunakan pada akhir 1990-an. Jadi sebelum C99, programmer tidak dapat mengandalkan ketersediaan jenis integer 64-bit sama sekali. Masalah itu diselesaikan dengan pengenalan long long
, yang minimal harus 64 bit. (Saya yakin ini sudah disediakan oleh GCC dan mungkin kompiler lain sebagai ekstensi).
Saat ini, banyak (tetapi tidak semua) sistem 64-bit menggunakan 64-bit long
dan tidak repot-repot membuat yang long long
lebih besar, jadi 64-bit juga dan dalam beberapa hal berlebihan. Itu mungkin sistem yang Anda kenal, tetapi mereka tidak mewakili semua yang ada di luar sana.
Saya pikir Anda tidak menyadari bahwa Anda membuat asumsi yang salah besar tentang cara kerja persyaratan lebar tipe C: ISO C hanya menetapkan rentang nilai minimum seperti magnitudo terkecil yang diizinkan LONG_MAX
dan LONG_MIN
(-2147483647, bukan 8 karena ISO C memungkinkan satu komplemen dan tanda / besarnya bilangan bulat bertanda, tidak hanya komplemen 2.) Implementasi aktual diperbolehkan untuk memiliki tipe yang lebih luas, seringkali untuk mencocokkan lebar register atau ukuran operan yang dapat dilakukan mesin target secara efisien.
Banyak yang telah ditulis tentang ini di Stack Overflow dan di tempat lain, yang tidak akan saya coba ulangi di sini. Lihat jugahttps://en.cppreference.com/w/c/language/arithmetic_types
Itu membawa Anda pada kesalahan dengan melihat pilihan tipe-lebar di x86-64 System V ABI dan menganggap bahwa implementasi C lainnya sama, saya kira. x86-64 adalah ISA 64-bit yang dapat bekerja secara efisien dengan integer 64-bit, jadi 64-bit long
adalah pilihan yang cukup masuk akal.
ABI yang waras untuk mesin 32-bit seperti i386 tidak akan menggunakan 64-bit long
karena itu tidak diperlukan, hanya 32-bit. Menggunakan 64-bit berarti tidak bisa masuk ke dalam satu register. Kompilasi dengan -m32
, atau kompilasi untuk ARM 32-bit. Godbolt juga memiliki GCC untuk AVR dan MSP430. Pada mesin 8-bit dan 16-bit tersebut, GCC memilih lebar terkecil yang diizinkan oleh ISO C (2-byte int
, dll.)
Pada 1999, x86-64 bahkan tidak ada. (Beberapa ISA 64-bit lainnya melakukannya, seperti Alpha). Jadi melihat salah satu dari 2 ABI arus utama agar memahami pilihan C99 tidak akan membawa Anda terlalu jauh.
Tentu saja C membutuhkan tipe yang dijamin setidaknya 64-bit, untuk memungkinkan orang menulis program yang secara efisien melakukan matematika integer 64-bit.
Dan BTW, x86-64 dapat melakukan hal-hal integer 32-bit seefisien 64-bit, terkadang lebih efisien. Jadi membuat long
tipe 64-bit bisa dibilang tidak bagus. Beberapa kode menggunakan long
karena mereka menginginkan tipe yang harus 32-bit, tetapi tidak mendapat manfaat dari membuatnya lebih luas. Untuk kode seperti itu, 64-bit long
hanya membuang jejak cache / bandwidth memori, dan ukuran kode (awalan REX). Di C99 pilihan yang ideal adalah int_least32_t
, tapi itu sangat panjang untuk mengetik dan jarang digunakan.
Tetapi OTOH, long
terkadang diharapkan menjadi "tipe paling efisien (1-register)", meskipun tidak ada jaminan seperti itu dan LLP64 ABI seperti Windows x64 dengan 32-bit long
tidak seperti itu.
Seluruh worm lain adalah int_fast32_t
pilihan IMO C99 dan x86-64 System V yang buruk untuk menjadikannya tipe 64-bit. (Saya memiliki jawaban setengah tertulis untuk Cpp uint32_fast_t menyelesaikan menjadi uint64_t tetapi lebih lambat untuk hampir semua operasi daripada uint32_t (x86_64). Mengapa diselesaikan menjadi uint64_t? Yang harus saya selesaikan ... int_fast32_t
menimbulkan pertanyaan "cepat untuk apa tujuan ", dan pada banyak penerapan, ini bukanlah yang Anda harapkan dalam banyak kasus.
Lihat juga
- C ++ - tipe integer tercepat?
- Bagaimana seharusnya tipe [u] int_fastN_t didefinisikan untuk x86_64, dengan atau tanpa x32 ABI?
- Mengapa uint32_t lebih disukai daripada uint_fast32_t?
- Mengapa uint_least16_t lebih cepat daripada uint_fast16_t untuk perkalian di x86_64?
- Pengoptimalan compiler diizinkan melalui tipe lebar tidak tetap "int", "least", dan "fast" C / C ++
Ada beberapa batasan tetapi pembuat kompiler bebas memilih panjang untuk tipe variabel C standar (char, short, int, long, long long). Biasanya char akan menjadi byte untuk arsitektur itu (kebanyakan compiler C berukuran 8 bit). Dan tentu saja Anda tidak bisa memiliki sesuatu yang lebih kecil lebih besar dari sesuatu yang lebih besar, panjang tidak bisa lebih kecil dari int. Tetapi tentu saja pada tahun 1999 kita melihat transisi x86 16 ke 32 bit dan misalnya int berubah dari 16 menjadi 32 dengan sejumlah alat tetapi lama tinggal 32. Kemudian transisi 32 ke 64 bit x86 terjadi dan tergantung pada alatnya, ada jenis yang tersedia untuk membantu.
Masalahnya sudah ada jauh sebelum ini dan solusinya bukanlah untuk memperbaiki panjang jenis, mereka, dalam aturan, hingga ukuran penulis kompilator. Tetapi pembuat kompilator perlu membuat file stdint.h yang cocok dengan alat dan target (stdint.h dikhususkan untuk alat dan target minimal dan dapat berupa versi alat dan opsi versi untuk alat itu, dll). Jadi, misalnya, uint32_t selalu 32 bit. Beberapa penulis akan mengubahnya menjadi int yang lain menjadi lama, dll di stdint.h mereka. Jenis variabel bahasa C tetap terbatas pada char, short, int, dll. Sesuai bahasa (uint32_t bukan jenis variabel, ia diubah menjadi jenis variabel melalui stdint.h). Solusi / solusi ini adalah cara untuk menjaga agar tidak semua menjadi gila dan menjaga bahasa tetap hidup.
Penulis akan sering memilih misalnya jika GPR adalah 16 bit dengan int menjadi 16 bit, dan jika 32 bit menjadi 32 bit dan seterusnya, tetapi mereka memiliki beberapa kebebasan.
Ya, ini secara khusus berarti bahwa tidak ada alasan untuk berasumsi bahwa dua alat untuk target tertentu (komputer tempat Anda membaca ini misalnya) menggunakan definisi yang sama untuk int dan long pada khususnya, dan jika Anda ingin menulis kode untuk platform ini yang dapat melakukan port di alat-alat ini (yang mendukung platform ini) kemudian menggunakan tipe stdint.h dan bukan int, long, dll ... Tentunya jika Anda melintasi platform msp430 mcu, sebuah arm mcu, sebuah mesin linux lengan , mesin berbasis x86, yang tipenya, bahkan untuk "toolchain" yang sama (gnu gcc dan binutils misalnya), tidak memiliki definisi yang sama untuk int dan long, dll. char dan short cenderung 8 dan 16 bit, int dan long cenderung paling bervariasi, terkadang ukurannya sama satu sama lain terkadang berbeda, tapi intinya jangan berasumsi.
Sangat mudah untuk mendeteksi ukuran, untuk versi compiler / target / opsi baris perintah, atau pergi ke rute stdint untuk meminimalkan masalah nanti.