Berapa ukuran bit panjang pada Windows 64-bit?

138

Belum lama ini, seseorang mengatakan kepada saya bahwa longitu bukan 64 bit pada mesin 64 bit dan saya harus selalu menggunakan int. Ini tidak masuk akal bagi saya. Saya telah melihat dokumen (seperti yang ada di situs resmi Apple) mengatakan bahwa longmemang 64 bit ketika mengkompilasi untuk CPU 64-bit. Saya mencari apa itu di Windows 64-bit dan menemukan

  • Windows: longdan intpanjangnya tetap 32-bit, dan tipe data baru khusus ditentukan untuk integer 64-bit.

(dari http://www.intel.com/cd/ids/developer/asmo-na/eng/197664.htm?page=2 )

Apa yang harus saya gunakan? Haruskah saya mendefinisikan sesuatu seperti uw, sw((un) signed width) sebagai longjika tidak pada Windows, dan sebaliknya melakukan pemeriksaan pada bitsize CPU target?

Csa77
sumber
Pada Windows dengan MSVC ++ int dan panjangnya adalah 32-bit: msdn.microsoft.com/en-us/library/3b2e7499.aspx . Namun, untuk memungkinkan misalnya vektor menyimpan lebih dari 4G item, size_t adalah 64 bit. Jadi kita perlu menggunakan int64_t daripada int untuk mengulang mis. Vektor yang mungkin berisi lebih dari item 4G.
Serge Rogatch
2
Di Cygwin sizeof(long) == 8, bahkan di Windows :-)
rustyx
@SergeRogatch mereka harus menggunakan size_tatau jenis iterator untuk mengulang, bukan intatauint64_t
phuclv
2
@ LưuVĩnhPhúc, dengan size_titu menjadi rumit mendekati angka negatif, karena size_tunsigned. Jadi for(size_t i=0; i<v.size()-2; i++)gagal untuk ukuran vektor 0 dan 1. Contoh lain: for(size_t i=v.size()-1; i>=0; i--).
Serge Rogatch
2
Jika Anda melakukan matematika pada pointer (yaitu dengan size_tnilai maka hasilnya harus disimpan dalam variabel ptrdiff_ttipe - yang dirancang cukup besar untuk menahan hasil seperti itu dan merupakan tipe yang ditandatangani untuk alasan itu!)
SlySven

Jawaban:

264

Di dunia Unix, ada beberapa kemungkinan pengaturan untuk ukuran integer dan pointer untuk platform 64-bit. Dua yang paling banyak digunakan adalah ILP64 (sebenarnya, hanya sedikit contoh ini; Cray adalah salah satunya) dan LP64 (untuk hampir semua yang lainnya). Akronim berasal dari 'int, long, pointer are 64-bit' dan 'long, pointer are 64-bit'.

Type           ILP64   LP64   LLP64
char              8      8       8
short            16     16      16
int              64     32      32
long             64     64      32
long long        64     64      64
pointer          64     64      64

Sistem ILP64 ditinggalkan dan digantikan oleh LP64 (yaitu, hampir semua peserta kemudian menggunakan LP64, berdasarkan rekomendasi dari grup Aspen; hanya sistem dengan warisan panjang operasi 64-bit yang menggunakan skema yang berbeda). Semua sistem Unix 64-bit modern menggunakan LP64. MacOS X dan Linux adalah sistem 64-bit modern.

Microsoft menggunakan skema berbeda untuk beralih ke 64-bit: LLP64 ('panjang, pointer 64-bit'). Ini memiliki arti bahwa perangkat lunak 32-bit dapat dikompilasi ulang tanpa perubahan. Ini memiliki kerugian menjadi berbeda dari apa yang orang lain lakukan, dan juga membutuhkan kode untuk direvisi untuk mengeksploitasi kapasitas 64-bit. Selalu ada revisi yang diperlukan; itu hanyalah serangkaian revisi yang berbeda dari yang dibutuhkan pada platform Unix.

Jika Anda merancang perangkat lunak Anda dengan nama tipe integer platform netral, mungkin menggunakan <inttypes.h>header C99 , yang, ketika tipe tersedia di platform, menyediakan, ditandatangani (terdaftar) dan tidak ditandatangani (tidak terdaftar; awalan dengan 'u'):

  • int8_t - bilangan bulat 8-bit
  • int16_t - bilangan bulat 16-bit
  • int32_t - bilangan bulat 32-bit
  • int64_t - Bilangan bulat 64-bit
  • uintptr_t - bilangan bulat unsigned yang cukup besar untuk menampung pointer
  • intmax_t- ukuran integer terbesar di platform (mungkin lebih besar dari int64_t)

Anda kemudian dapat mengkodekan aplikasi Anda menggunakan jenis ini di tempat yang penting, dan sangat berhati-hati dengan jenis sistem (yang mungkin berbeda). Ada intptr_ttipe - tipe integer bertanda tangan untuk memegang pointer; Anda harus berencana untuk tidak menggunakannya, atau hanya menggunakannya sebagai hasil pengurangan dua uintptr_tnilai ( ptrdiff_t).

Tapi, seperti yang ditunjukkan pertanyaan tersebut (tidak percaya), ada sistem yang berbeda untuk ukuran tipe data integer pada mesin 64-bit. Terbiasalah; dunia tidak akan berubah.

Jonathan Leffler
sumber
12
Bagi pengguna yang sudah cukup lama, transisi 64-bit memiliki beberapa kesamaan dengan transisi 16-bit ke 32-bit pada pertengahan 80-an. Ada komputer yang IL32 dan yang lainnya L32 (mengadaptasi notasi baru ke masalah lama). Terkadang 'int' adalah 16-bit, terkadang 32-bit.
Jonathan Leffler
4
Jangan lupa bahwa ini hanya berlaku untuk bahasa C-ish. Yang lain memiliki spesifikasi yang lebih waras di mana a) penulis kompilator tidak diperbolehkan untuk memilih ukuran tipe data secara sukarela atau b) representasi fisik dari tipe data tidak "bocor" atau c) bilangan bulat selalu besar tak terhingga.
Jörg W Mittag
2
Benar - tetapi untuk bahasa yang menentukan perilakunya, tidak ada masalah sejak awal. Misalnya, Java memiliki 'long', tetapi ukurannya tetap (64-bit?), Di semua platform. Jadi, tidak ada masalah porting ke mesin 64-bit; ukurannya tidak berubah.
Jonathan Leffler
17
@TomFobear: ILP64 menyajikan satu masalah utama - apa yang Anda sebut tipe 32-bit? Atau, jika Anda menyebut tipe 32-bit short, apa yang Anda sebut tipe 16-bit? Dan jika Anda memanggil tipe 16-bit charuntuk UTF-16 dll, apa yang Anda sebut tipe 8-bit? Jadi, menggunakan LP64 membuat Anda memiliki 8-bit char, 16-bit short, 32-bit int, 64-bit long, dengan ruang untuk ekspansi ke atas ke 128-bit long longketika (jika?) Itu menjadi relevan. Setelah itu, Anda memiliki lebih banyak kekuatan 256 daripada nama Anda di C (yah, saya kira Anda dapat memiliki 256-bit intmax_t, dan baru setelah itu Anda kehabisan). Ada manfaatnya untuk LP64.
Jonathan Leffler
2
Mungkin ini jelas bagi kalian, tapi saya pikir perlu dicatat bahwa C # menggunakan ukuran integer yang berbeda dari yang lainnya. Saya baru-baru ini tersandung interfacing dengan DLL karena C # menggunakan 64-bit longs ( msdn.microsoft.com/en-us/library/ms173105.aspx ).
Compholio
57

Tidak jelas apakah pertanyaannya tentang kompiler Microsoft C ++ atau Windows API. Namun, tidak ada tag [c ++] jadi saya menganggap ini tentang API Windows. Beberapa jawaban menderita pembusukan tautan jadi saya menyediakan tautan lain yang bisa membusuk.


Untuk informasi tentang jenis Windows API seperti INT, LONGdll. Ada halaman di MSDN:

Jenis Data Windows

Informasi ini juga tersedia di berbagai file header Windows seperti WinDef.h. Saya telah membuat daftar beberapa jenis yang relevan di sini:

Ketik | S / U | x86 | x64
---------------------------- + ----- + -------- + ------ -
BYTE, BOOLEAN | U | 8 bit | 8 bit
---------------------------- + ----- + -------- + ------ -
PENDEK | S | 16 bit | 16 bit
USHORT, WORD | U | 16 bit | 16 bit
---------------------------- + ----- + -------- + ------ -
INT, PANJANG | S | 32 bit | 32 bit
UINT, ULONG, DWORD | U | 32 bit | 32 bit
---------------------------- + ----- + -------- + ------ -
INT_PTR, LONG_PTR, LPARAM | S | 32 bit | 64 bit
UINT_PTR, ULONG_PTR, WPARAM | U | 32 bit | 64 bit
---------------------------- + ----- + -------- + ------ -
PANJANG | S | 64 bit | 64 bit
ULONGLONG, QWORD | U | 64 bit | 64 bit

Kolom "S / U" menunjukkan tanda tangan / tidak bertanda tangan.

Martin Liversage
sumber
4

Artikel di MSDN ini merujuk pada sejumlah alias tipe (tersedia di Windows) yang sedikit lebih eksplisit sehubungan dengan lebarnya:

http://msdn.microsoft.com/en-us/library/aa505945.aspx

Misalnya, meskipun Anda dapat menggunakan ULONGLONG untuk mereferensikan nilai integral 64-bit unsigned, Anda juga dapat menggunakan UINT64. (Hal yang sama berlaku untuk ULONG dan UINT32.) Mungkin ini akan sedikit lebih jelas?

Ruben
sumber
1
Apakah ada jaminan bahwa uint32_t dan DWORD dapat dipertukarkan? Tidak sulit untuk membayangkan bahwa mereka tidak mungkin [misalnya jika yang pertama adalah 32-bit intdan yang kedua adalah 32-bit long, gcc akan menganggap pointer ke satu jenis tidak akan dapat membuat alias yang lain meskipun representasi mereka cocok].
supercat
4

Microsoft juga telah mendefinisikan UINT_PTR dan INT_PTR untuk bilangan bulat yang berukuran sama dengan penunjuk.

Berikut adalah daftar tipe khusus Microsoft - itu bagian dari referensi driver mereka, tapi saya yakin ini juga berlaku untuk pemrograman umum.

Mark Ransom
sumber
2

Cara termudah untuk memahaminya untuk kompiler / platform Anda:

#include <iostream>

int main() {
  std::cout << sizeof(long)*8 << std::endl;
}

Perkalian dengan 8 adalah mendapatkan bit dari byte.

Saat Anda membutuhkan ukuran tertentu, seringkali paling mudah menggunakan salah satu tipe pustaka yang sudah ditentukan sebelumnya. Jika itu tidak diinginkan, Anda dapat melakukan apa yang sering terjadi dengan perangkat lunak autoconf dan meminta sistem konfigurasi menentukan jenis yang tepat untuk ukuran yang diperlukan.

Paul de Vrieze
sumber
4
Bukan berarti itu penting, tetapi byte 8-bit sebenarnya bukan bagian dari spesifikasi C (klausul 3.6 dan 5.2.4.2.1 dari standar C). Meskipun Anda akan kesulitan menemukan mesin yang bukan 8 bit, Anda dapat memeriksa LONG_BIT untuk melihat seberapa besar tipe data panjang Anda.
Andres
Tentu saja, Anda benar, ini sebenarnya bergantung pada arsitektur ("unit penyimpanan data yang dapat dialamatkan cukup besar untuk menampung setiap anggota kumpulan karakter dasar lingkungan eksekusi"), tetapi arsitektur yang paling umum digunakan yang sama dengan 8 bit.
Paul de Vrieze
Tapi OP tidak bertanya tentang nya compiler / platform; dia bertanya secara khusus tentang Windows 64-bit - mungkin karena dia tidak memiliki akses mudah ke sistem Windows 64-bit untuk diuji.
Quuxplusone
0

Ukuran bit longpada platform Windows adalah 32 bit (4 byte).

Anda dapat memeriksa ini menggunakan sizeof(long).

BeeOnRope
sumber
-2

Jika Anda perlu menggunakan bilangan bulat dengan panjang tertentu, Anda mungkin harus menggunakan beberapa header platform independen untuk membantu Anda. Boost adalah tempat yang bagus untuk dilihat.

PolyThinker
sumber