Panjang lama di c99

Jan 10 2021

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 longsudah 8demikian, mengapa perlu ditambahkan long longtipe lain ? Apa yang dilakukannya pada kompiler / arsitektur?

Jawaban

6 chux-ReinstateMonica Jan 10 2021 at 05:36

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 longdan int32 atau 16 bit.

Membutuhkan long64-bit akan merusak basis kode. Ini adalah perhatian utama.


Namun membutuhkan longuntuk 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 longsebagai 32-bit atau 64-bit (atau lainnya) memungkinkan untuk transisi.

Berbagai fungsi masuk / kembali longseperti fseek(), ftell(). Mereka mendapat manfaat longkarena lebih dari 32-bit untuk dukungan file besar.

Praktik yang disarankan mendorong pemahaman yang lebih luas long: "Jenis yang digunakan untuk size_tdan ptrdiff_ttidak boleh memiliki peringkat konversi bilangan bulat yang lebih besar dari itu signed long intkecuali 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_t32/64/128/256 bits.

IAC, saya melihat jenis lebar tetap intN_tsemakin populer selama longdan long long. Saya cenderung menggunakan fixed jenis lebar atau bool, ( unsigned) char, int/ unsigned, size_t, ( u) intmax_tdan cuti signed char, ( unsigned) short, ( unsigned) long, ( unsigned) long longuntuk kasus-kasus khusus.

4 dbush Jan 10 2021 at 05:26

Standar C hanya menjamin bahwa intcan menjadi (secara bebas) 2 byte, a longcan menjadi 4 byte, dan a long longcan menjadi 8 byte.

Nyatanya, MSVC tetap menggunakan 4 byte longmeski sudah 4 byte int.

3 NateEldredge Jan 10 2021 at 05:38

Satu-satunya persyaratan yang relevan untuk intdan long, dulu dan sekarang, adalah intminimal harus 16 bit dan longminimal 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 longdan tidak repot-repot membuat yang long longlebih 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.

2 PeterCordes Jan 10 2021 at 10:29

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_MAXdan 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 longadalah pilihan yang cukup masuk akal.

ABI yang waras untuk mesin 32-bit seperti i386 tidak akan menggunakan 64-bit longkarena 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 longtipe 64-bit bisa dibilang tidak bagus. Beberapa kode menggunakan longkarena mereka menginginkan tipe yang harus 32-bit, tetapi tidak mendapat manfaat dari membuatnya lebih luas. Untuk kode seperti itu, 64-bit longhanya 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, longterkadang diharapkan menjadi "tipe paling efisien (1-register)", meskipun tidak ada jaminan seperti itu dan LLP64 ABI seperti Windows x64 dengan 32-bit longtidak seperti itu.

Seluruh worm lain adalah int_fast32_tpilihan 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_tmenimbulkan 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 ++
old_timer Jan 11 2021 at 06:16

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.