ขนาดบิตยาวของ Windows 64 บิตคือเท่าใด


137

จะไม่นานที่ผ่านมามีคนบอกผมว่าlongไม่ได้ 64 บิต 64 intเครื่องบิตและฉันควรใช้ สิ่งนี้ไม่สมเหตุสมผลสำหรับฉัน ฉันเคยเห็นเอกสาร (เช่นที่อยู่ในเว็บไซต์อย่างเป็นทางการของ Apple) บอกว่าlongเป็น 64 บิตเมื่อรวบรวมสำหรับ CPU 64 บิต ฉันค้นหาสิ่งที่อยู่บน Windows 64 บิตและพบว่า

  • Windows: longและintยังคงมีความยาว 32 บิตและมีการกำหนดชนิดข้อมูลใหม่พิเศษสำหรับจำนวนเต็ม 64 บิต

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

ฉันควรใช้อะไร ฉันควรกำหนดสิ่งที่ต้องการuw, sw((un) ความกว้างที่มีการเซ็นlongชือ) เป็นถ้าไม่ได้อยู่ใน Windows และควรตรวจสอบบิตซีพียูเป้าหมายหรือไม่


บน Windows กับ MSVC ++ int และยาว 32 บิต: msdn.microsoft.com/en-us/library/3b2e7499.aspx อย่างไรก็ตามเพื่ออนุญาตให้เวกเตอร์จัดเก็บรายการมากกว่า 4G รายการ size_t คือ 64 บิต ดังนั้นเราจึงจำเป็นต้องใช้ int64_t แทนที่จะเป็น int เพื่อทำซ้ำเช่นเวกเตอร์ซึ่งอาจมีมากกว่า 4G รายการ
Serge Rogatch


@SergeRogatch พวกเขาควรใช้size_tหรือชนิดตัววนซ้ำเพื่อย้ำไม่ใช่intหรือint64_t
phuclv

2
@ LưuVĩnhPhúcโดยที่size_tมันใกล้กับตัวเลขติดลบเพราะsize_tไม่ได้ลงนาม ดังนั้นfor(size_t i=0; i<v.size()-2; i++)ล้มเหลวสำหรับขนาดเวกเตอร์ 0 และ 1 for(size_t i=v.size()-1; i>=0; i--)ตัวอย่างหนึ่ง:
Serge Rogatch

2
หากคุณกำลังทำคณิตศาสตร์กับพอยน์เตอร์ (เช่นมีsize_tค่าผลลัพธ์ควรเก็บไว้ในตัวแปรptrdiff_tประเภท - ซึ่งถูกออกแบบมาให้มีขนาดใหญ่พอที่จะเก็บผลลัพธ์ดังกล่าวและเป็นประเภทที่เซ็นชื่อด้วยเหตุผลนั้น!)
SlySven

คำตอบ:


261

ในโลก Unix มีข้อตกลงที่เป็นไปได้สองสามประการสำหรับขนาดของจำนวนเต็มและตัวชี้สำหรับแพลตฟอร์ม 64 บิต ทั้งสองส่วนใหญ่ใช้กันอย่างแพร่หลายคือ ILP64 (อันที่จริงมีเพียงไม่กี่ตัวอย่างเท่านั้น; Cray เป็นหนึ่งในนั้น) และ LP64 (สำหรับเกือบทุกอย่าง) ตัวย่อมาจาก 'int, long, pointers คือ 64-bit' และ 'long, pointers เป็น 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

ระบบ ILP64 ถูกทอดทิ้งในความโปรดปรานของLP64 (นั่นคือเกือบทั้งหมดต่อมาใช้ LP64 ตามคำแนะนำของกลุ่มแอสเพนระบบเดียวที่มีมรดกยาวนานของการทำงาน 64 บิตใช้รูปแบบที่แตกต่างกัน) ระบบ Unix 64 บิตที่ทันสมัยทั้งหมดใช้ LP64 MacOS X และ Linux เป็นระบบ 64 บิตที่ทันสมัย

Microsoft ใช้รูปแบบที่แตกต่างกันสำหรับการเปลี่ยนเป็น 64 บิต: LLP64 ('ตัวชี้ความยาวยาวคือ 64 บิต') นี่เป็นข้อดีของความหมายที่ว่าซอฟต์แวร์ 32- บิตสามารถทำการคอมไพล์ใหม่ได้โดยไม่มีการเปลี่ยนแปลง มันมีข้อผิดพลาดที่แตกต่างจากสิ่งที่คนอื่นทำและต้องมีการแก้ไขโค้ดเพื่อใช้ประโยชน์จากความจุ 64- บิต จำเป็นต้องมีการแก้ไขเสมอ; มันเป็นชุดการแก้ไขที่แตกต่างจากชุดที่ต้องการบนแพลตฟอร์ม Unix

หากคุณออกแบบซอฟต์แวร์ของคุณรอบ ๆ ชื่อประเภทจำนวนเต็มเป็นกลางแพลตฟอร์มอาจใช้<inttypes.h>ส่วนหัวC99 ซึ่งเมื่อประเภทที่มีอยู่บนแพลตฟอร์มให้ในลงชื่อ (จดทะเบียน) และไม่ได้ลงนาม (ไม่อยู่ในรายการ; คำนำหน้าด้วย 'u'):

  • int8_t - จำนวนเต็ม 8 บิต
  • int16_t - จำนวนเต็ม 16 บิต
  • int32_t - จำนวนเต็ม 32 บิต
  • int64_t - จำนวนเต็ม 64 บิต
  • uintptr_t - จำนวนเต็มที่ไม่ได้ลงชื่อมีขนาดใหญ่พอที่จะเก็บพอยน์เตอร์
  • intmax_t- ขนาดใหญ่ที่สุดบนแพลตฟอร์ม (อาจใหญ่กว่าint64_t)

จากนั้นคุณสามารถโค้ดแอปพลิเคชันของคุณโดยใช้ประเภทเหล่านี้ในที่ที่มันสำคัญและระมัดระวังอย่างมากกับประเภทของระบบ (ซึ่งอาจแตกต่างกัน) มีintptr_tประเภทคือ- ประเภทจำนวนเต็มลงนามสำหรับการถือพอยน์เตอร์; คุณควรวางแผนที่จะไม่ใช้มันหรือใช้มันเป็นผลมาจากการลบสองuintptr_tค่า ( ptrdiff_t)

แต่ตามที่คำถามชี้ให้เห็น (ในการปฏิเสธศรัทธา) มีระบบที่แตกต่างกันสำหรับขนาดของชนิดข้อมูลจำนวนเต็มบนเครื่อง 64 บิต รับใช้มัน โลกจะไม่เปลี่ยนแปลง


12
สำหรับผู้ที่ใช้งานมานานพอแล้วการเปลี่ยน 64- บิตมีความคล้ายคลึงกันกับการเปลี่ยน 16-32 บิตในช่วงกลาง 80 มีคอมพิวเตอร์ที่เป็น IL32 และคอมพิวเตอร์อื่น ๆ ที่เป็น L32 (ปรับข้อความใหม่ให้ตรงกับปัญหาเก่า) บางครั้ง 'int' คือ 16 บิตบางครั้ง 32 บิต
Jonathan Leffler

4
อย่าลืมว่าสิ่งนี้ใช้ได้กับภาษา C-ish เท่านั้น คนอื่น ๆ มีคุณสมบัติของ saner โดยที่ a) ผู้เขียนคอมไพเลอร์ไม่ได้รับอนุญาตให้เลือกขนาดของประเภทข้อมูลที่ต้องการหรือ b) การเป็นตัวแทนทางกายภาพของประเภทข้อมูลนั้นจะไม่ "รั่วไหล" หรือ c) จำนวนเต็มขนาดใหญ่เสมอ
Jörg W Mittag

2
จริง - แต่สำหรับภาษาที่ระบุลักษณะการทำงานจะไม่มีปัญหาในตอนแรก ตัวอย่างเช่น Java มี 'ยาว' แต่ขนาดคงที่ (64- บิต?) ในทุกแพลตฟอร์ม ดังนั้นจึงไม่มีปัญหาในการย้ายพอร์ตไปยังเครื่อง 64 บิต; ขนาดจะไม่เปลี่ยนแปลง
Jonathan Leffler

17
@TomFobear: ILP64 นำเสนอหนึ่งประเด็นสำคัญ - คุณเรียกประเภท 32 บิตว่าอย่างไร หรือถ้าคุณเรียกชนิด 32 บิตshortคุณจะเรียกประเภท 16 บิตว่าอย่างไร และถ้าคุณเรียกใช้ชนิด 16 บิตcharสำหรับ UTF-16 เป็นต้นคุณเรียกประเภท 8 บิตเป็นอย่างไร ดังนั้นการใช้ LP64 จะทำให้คุณมี 8 บิตchar, 16- บิตshort, 32- บิตint, 64- บิตlongโดยมีที่ว่างสำหรับการขยายขึ้นไปเป็น 128- บิตlong longเมื่อ (ถ้า?) ที่เกี่ยวข้อง หลังจากนั้นคุณมีพลังมากกว่า 256 กว่าคุณมีชื่อใน C (เช่นกันฉันคิดว่าคุณน่าจะมี 256- บิตintmax_tแล้วคุณจะหมดแล้ว) มีบุญถึง LP64
Jonathan Leffler

2
บางทีนี่อาจจะชัดเจนสำหรับพวกคุณ แต่ฉันคิดว่ามันคุ้มค่าที่จะสังเกตว่า C # ใช้ขนาดจำนวนเต็มแตกต่างจากทุกอย่าง ฉันเพิ่งได้รับการติดต่อกับ DLL เนื่องจาก C # ใช้ความยาว 64 บิต ( msdn.microsoft.com/en-us/library/ms173105.aspx )
Compholio

57

ไม่ชัดเจนหากคำถามเกี่ยวกับคอมไพเลอร์ Microsoft C ++ หรือ Windows API อย่างไรก็ตามไม่มีแท็ก [c ++] ดังนั้นฉันคิดว่ามันเกี่ยวกับ Windows API คำตอบบางส่วนได้รับความเดือดร้อนจากการเชื่อมโยงที่เน่าดังนั้นฉันจึงให้การเชื่อมโยงอื่นที่สามารถเน่า


สำหรับข้อมูลเกี่ยวกับประเภทของ Windows API เช่นINT, LONGฯลฯ มีหน้า MSDN:

Windows Data Types

ข้อมูลที่ยังมีอยู่ในไฟล์ส่วนหัวของ Windows WinDef.hต่างๆเช่น ฉันมีรายการประเภทที่เกี่ยวข้องสองสามรายการที่นี่:

ประเภท | S / U | x86 | x64
---------------------------- + ----- + -------- + ------ -
ไบต์บูลีน U | 8 บิต | 8 บิต
---------------------------- + ----- + -------- + ------ -
SHORT | S | 16 บิต | 16 บิต
USHORT, WORD | U | 16 บิต | 16 บิต
---------------------------- + ----- + -------- + ------ -
INT, LONG | S | 32 บิต | 32 บิต
UINT, ULONG, DWORD | U | 32 บิต | 32 บิต
---------------------------- + ----- + -------- + ------ -
INT_PTR, LONG_PTR, LPARAM | S | 32 บิต | 64 บิต
UINT_PTR, ULONG_PTR, WPARAM | U | 32 บิต | 64 บิต
---------------------------- + ----- + -------- + ------ -
ลองหลง S | 64 บิต | 64 บิต
ULONGLONG, QWORD | U | 64 บิต | 64 บิต

คอลัมน์ "S / U" หมายถึงการลงชื่อ / ไม่ได้ลงชื่อ


4

บทความนี้ใน MSDN อ้างอิงถึงนามแฝงประเภท (มีอยู่ใน Windows) ที่ชัดเจนกว่านี้เล็กน้อยตามความกว้าง:

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

ตัวอย่างเช่นแม้ว่าคุณสามารถใช้ ULONGLONG เพื่ออ้างอิงค่าอินทิกรัลที่ไม่ได้ลงชื่อแบบ 64 บิต แต่คุณยังสามารถใช้ UINT64 ได้ (เช่นเดียวกันสำหรับ ULONG และ UINT32) บางทีสิ่งเหล่านี้จะชัดเจนขึ้นหรือไม่


1
มีการรับประกันว่า uint32_t และ DWORD จะสามารถใช้แทนกันได้หรือไม่? ไม่ใช่เรื่องยากที่จะจินตนาการว่าพวกเขาอาจจะไม่ [เช่นถ้าอดีตเป็น 32- บิตintและหลังเป็น 32- บิตlong, gcc จะถือว่าตัวชี้ไปยังประเภทหนึ่งจะไม่สามารถนามแฝงอื่น ๆ แม้จะเป็นตัวแทนการจับคู่ของพวกเขา]
supercat

4

Microsoft ได้กำหนด UINT_PTR และ INT_PTR สำหรับจำนวนเต็มที่มีขนาดเท่ากับตัวชี้

นี่คือรายการประเภทเฉพาะของ Microsoft - เป็นส่วนหนึ่งของการอ้างอิงไดรเวอร์ของพวกเขา แต่ฉันเชื่อว่ามันถูกต้องสำหรับการเขียนโปรแกรมทั่วไปเช่นกัน


2

วิธีที่ง่ายที่สุดในการทำความรู้จักกับคอมไพเลอร์ / แพลตฟอร์มของคุณ:

#include <iostream>

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

Themultiplication by 8 คือการรับบิตจากไบต์

เมื่อคุณต้องการขนาดที่เฉพาะเจาะจงมักจะง่ายที่สุดในการใช้หนึ่งในประเภทที่กำหนดไว้ล่วงหน้าของห้องสมุด หากไม่พึงประสงค์คุณสามารถทำสิ่งที่เกิดขึ้นบ่อยครั้งกับซอฟต์แวร์ autoconf และให้ระบบกำหนดประเภทที่เหมาะสมสำหรับขนาดที่ต้องการ


4
ไม่ใช่ว่ามันมีความสำคัญ แต่ไบต์ 8 บิตไม่ใช่ส่วนหนึ่งของข้อมูลจำเพาะ C (ข้อ 3.6 และ 5.2.4.2.1 ของมาตรฐาน C) แม้ว่าคุณจะกดยากเพื่อค้นหาเครื่องที่ไม่ได้เป็น 8 บิต แต่คุณสามารถตรวจสอบ LONG_BIT เพื่อดูว่าประเภทข้อมูลของคุณยาวขนาดไหน
Andres

แน่นอนว่าคุณถูกต้องมันขึ้นอยู่กับสถาปัตยกรรมจริง ๆ ("หน่วยเก็บข้อมูลที่สามารถกำหนดแอดเดรสได้มีขนาดใหญ่พอที่จะทำให้สมาชิกของชุดอักขระพื้นฐานของสภาพแวดล้อมการประมวลผล") แต่สถาปัตยกรรมที่ใช้บ่อยที่สุดที่มีขนาด 8 บิต
Paul de Vrieze

แต่ OP ไม่ได้ถามเกี่ยวกับของเขาคอมไพเลอร์ / แพลตฟอร์ม; เขาถามโดยเฉพาะเกี่ยวกับ Windows 64 บิต - น่าจะเป็นเพราะเขาไม่สามารถเข้าถึงระบบ Windows 64 บิตที่สะดวกในการทดสอบ
Quuxplusone

0

ขนาดเป็นบิตของ longบนแพลตฟอร์ม Windows คือ 32 บิต (4 ไบต์)

sizeof(long)คุณสามารถตรวจสอบการใช้นี้


-2

หากคุณต้องการใช้จำนวนเต็มที่มีความยาวแน่นอนคุณควรใช้ส่วนหัวที่เป็นอิสระของแพลตฟอร์มเพื่อช่วยคุณ Boost เป็นสถานที่ที่ดีในการดู

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.