คำสั่งห้ามของ `long 'สมเหตุสมผลหรือไม่?


109

ในปัจจุบันข้ามแพลตฟอร์ม C ++ (หรือ C) โลกเรามี :

Data model  | short |   int |   long | long long | pointers/size_t  | Sample operating systems
... 
LLP64/IL32P64   16      32      32     64           64                Microsoft Windows (x86-64 and IA-64)
LP64/I32LP64    16      32      64     64           64                Most Unix and Unix-like systems, e.g. Solaris, Linux, BSD, and OS X; z/OS
...

สิ่งนี้หมายความว่าในวันนี้คือว่าสำหรับจำนวนเต็ม "ธรรมดา" (ลงนาม) intจะพอเพียงและยังสามารถใช้เป็นประเภทจำนวนเต็มเริ่มต้นเมื่อเขียนรหัสแอปพลิเคชัน C ++ มันจะยัง - เพื่อวัตถุประสงค์ในทางปฏิบัติในปัจจุบัน - มีขนาดที่สอดคล้องกันในทุกแพลตฟอร์ม

Iff a use case ต้องการอย่างน้อย 64 bits วันนี้เราสามารถใช้งานlong longได้แม้ว่าอาจจะใช้หนึ่งในประเภทที่ระบุพยานบุคคลหรือ__int64ประเภทอาจทำให้รู้สึกมากขึ้น

สิ่งนี้longอยู่ตรงกลางและเรากำลังพิจารณาห้ามการใช้งานlongจากรหัสแอปพลิเคชันของเราทันที

สิ่งนี้จะสมเหตุสมผลหรือมีกรณีสำหรับการใช้งานlongในรหัส C ++ (หรือ C) ที่ทันสมัยที่ต้องเรียกใช้ข้ามแพลตฟอร์ม? (แพลตฟอร์มเป็นเดสก์ท็อป, อุปกรณ์มือถือ แต่ไม่ใช่สิ่งที่ต้องการไมโครคอนโทรลเลอร์, DSP และอื่น ๆ )


ลิงก์พื้นหลังที่น่าสนใจอาจเป็นไปได้:


14
คุณจะจัดการกับการโทรไปยังห้องสมุดที่ใช้เวลานานแค่ไหน?
Ángel

14
longเป็นวิธีเดียวที่จะรับประกัน 32 บิต intอาจเป็น 16 บิตดังนั้นสำหรับบางแอปพลิเคชันก็ไม่เพียงพอ ใช่intบางครั้งก็เป็น 16 บิตสำหรับคอมไพเลอร์สมัยใหม่ ใช่คนเขียนซอฟต์แวร์บนไมโครคอนโทรลเลอร์ ฉันเถียงคนเขียนซอฟต์แวร์ที่มีผู้ใช้บนไมโครคอนโทรลเลอร์มากกว่าบนพีซีที่มีอุปกรณ์ iPhone และ Android เพิ่มขึ้นและไม่ต้องพูดถึงการเพิ่มขึ้นของ Arduinos เป็นต้น
slebetman

53
ทำไมไม่แบนอักขระ char, short, int, long และ long และใช้ [u] ประเภท intXX_t
immibis

7
@slebetman ฉันขุดลึกลงไปอีกนิดปรากฏว่าข้อกำหนดยังคงอยู่แม้ว่าจะซ่อนอยู่ใน§3.9.1.3โดยที่รัฐมาตรฐาน C ++: "ประเภทจำนวนเต็มที่ลงนามและไม่ได้ลงนามจะต้องเป็นไปตามข้อ จำกัด ที่กำหนดในมาตรฐาน C ส่วน 5.2 4.2.1." และในมาตรฐาน C §5.2.4.2.1มันระบุช่วงต่ำสุดตรงตามที่คุณเขียน คุณพูดถูก :) เห็นได้ชัดว่าการเป็นเจ้าของสำเนาของมาตรฐาน C ++ นั้นไม่เพียงพอเราจำเป็นต้องค้นหาสำเนาของมาตรฐาน C เช่นกัน
Tommy Andersen

11
คุณกำลังพลาดโลกของ DOSBox / Turbo C ++ ซึ่งintยังคงเป็น 16 บิต ฉันเกลียดที่จะพูด แต่ถ้าคุณกำลังจะเขียนเกี่ยวกับ "โลกข้ามแพลตฟอร์มของวันนี้" คุณไม่สามารถเพิกเฉยต่อชมพูทวีปทั้งหมด
การแข่งขัน Lightness ใน Orbit

คำตอบ:


17

เหตุผลเดียวที่ฉันจะใช้longวันนี้คือเมื่อโทรหรือใช้งานอินเทอร์เฟซภายนอกที่ใช้

อย่างที่คุณพูดในโพสต์สั้น ๆ และ int มีลักษณะที่เสถียรพอสมควรในทุกแพลตฟอร์มเดสก์ท็อป / เซิร์ฟเวอร์ / มือถือที่สำคัญทั้งหมดและฉันไม่เห็นเหตุผลที่จะเปลี่ยนแปลงในอนาคตอันใกล้นี้ ดังนั้นฉันเห็นเหตุผลเล็กน้อยที่จะหลีกเลี่ยงพวกเขาโดยทั่วไป

longในทางตรงกันข้ามเป็นระเบียบ ในระบบ 32 บิตทั้งหมดฉันรู้ว่ามันมีคุณสมบัติดังต่อไปนี้

  1. มันมีขนาด 32 บิตอย่างแน่นอน
  2. มันมีขนาดเท่ากับที่อยู่หน่วยความจำ
  3. มันมีขนาดเท่ากับหน่วยข้อมูลที่ใหญ่ที่สุดที่สามารถเก็บไว้ในทะเบียนปกติและทำงานด้วยคำสั่งเดียว

โค้ดจำนวนมากถูกเขียนโดยอิงจากคุณลักษณะเหล่านี้อย่างน้อยหนึ่งอย่าง อย่างไรก็ตามด้วยการย้ายไปยัง 64- บิตมันเป็นไปไม่ได้ที่จะรักษาพวกเขาทั้งหมด แพลตฟอร์มที่เหมือน Unix ใช้สำหรับ LP64 ซึ่งรักษาลักษณะที่ 2 และ 3 ในราคาลักษณะ 1 Win64 ไปสำหรับ LLP64 ซึ่งเก็บรักษาคุณสมบัติ 1 ไว้ในราคาลักษณะ 2 และ 3 ผลลัพธ์คือคุณไม่สามารถพึ่งพาคุณลักษณะเหล่านั้นได้อีก และ IMO นั้นมีเหตุผลให้ใช้longน้อย

หากคุณต้องการประเภทที่ว่า 32 int32_tบิตในขนาดที่คุณควรใช้

หากคุณต้องการประเภทที่มีขนาดเดียวกันกับตัวชี้คุณควรใช้intptr_t(หรือดีกว่าuintptr_t)

หากคุณต้องการประเภทที่เป็นรายการที่ใหญ่ที่สุดที่สามารถทำงานได้ในการลงทะเบียน / คำสั่งเดียวน่าเสียดายที่ฉันไม่คิดว่ามาตรฐานจะมีให้ size_tควรจะเป็นสิทธิบนแพลตฟอร์มที่พบมากที่สุด แต่มันจะไม่เกี่ยวกับx32


PS

ฉันจะไม่รำคาญกับประเภท "เร็ว" หรือ "น้อยที่สุด" ว่า "อย่างน้อย" ประเภทเท่านั้นไม่ว่าถ้าคุณดูแลเกี่ยวกับ portablility CHAR_BIT != 8สถาปัตยกรรมปิดบังจริงๆที่ ขนาดของประเภท "เร็ว" ในทางปฏิบัติดูเหมือนว่าจะค่อนข้างดี ลีนุกซ์ดูเหมือนว่าจะทำให้มันมีขนาดเท่ากับตัวชี้อย่างน้อย, ซึ่งมันโง่บนแพลตฟอร์ม 64 บิตพร้อมการสนับสนุน 32 บิตที่รวดเร็วเช่น x86-64 และ arm64 IIRC iOS ทำให้มีขนาดเล็กที่สุด ฉันไม่แน่ใจว่าระบบอื่น ๆ ทำอะไร


PPS

เหตุผลหนึ่งที่ใช้unsigned long(แต่ไม่ธรรมดาlong) ก็เพราะว่ามันเป็น gauranteed ที่มีพฤติกรรมแบบโมดูโล น่าเสียดายที่กฎการเลื่อนระดับประเภทที่ไม่ได้ลงนามของ C มีขนาดเล็กกว่าที่intไม่มีพฤติกรรมแบบโมดูโล

ในทุกแพลตฟอร์มที่สำคัญในปัจจุบันuint32_tมีขนาดเท่ากันหรือใหญ่กว่า int และด้วยเหตุนี้จึงมีพฤติกรรมแบบโมดูโล อย่างไรก็ตามมีในอดีตและในทางทฤษฎีอาจมีแพลตฟอร์มในอนาคตที่int64- บิตและด้วยเหตุนี้uint32_tไม่มีพฤติกรรมแบบโมดูโล

โดยส่วนตัวแล้วฉันจะบอกว่าเป็นการดีกว่าถ้าคุณจะบังคับพฤติกรรมแบบโมดูโลให้ดีขึ้นโดยใช้ "1u *" หรือ "0u +" ในตอนเริ่มต้นของสมการของคุณ


1
ชนิด "ขนาดที่ระบุ" ทั้งหมดจะมีประโยชน์มากขึ้นหากพวกเขาสามารถระบุความหมายที่แตกต่างจากประเภทในตัว ตัวอย่างเช่นมันจะมีประโยชน์ที่จะมีประเภทซึ่งจะใช้ mod-65536 เลขคณิตโดยไม่คำนึงถึงขนาดของ "int" พร้อมกับประเภทที่จะสามารถถือตัวเลข 0 ถึง 65535 แต่สามารถสุ่มและไม่จำเป็นต้องมีความสามารถอย่างสม่ำเสมอของการถือครองตัวเลขที่มากกว่านั้น ประเภทขนาดใดที่เร็วที่สุดสำหรับเครื่องส่วนใหญ่จะขึ้นอยู่กับบริบทดังนั้นความสามารถในการอนุญาตให้คอมไพเลอร์เลือกโดยพลการจะเหมาะสมที่สุดสำหรับความเร็ว
supercat

204

ดังที่คุณกล่าวถึงในคำถามของคุณซอฟต์แวร์ที่ทันสมัยนั้นเป็นข้อมูลเกี่ยวกับการทำงานร่วมกันระหว่างแพลตฟอร์มและระบบบนอินเทอร์เน็ต มาตรฐาน C และ C ++ ให้ช่วงสำหรับขนาดชนิดจำนวนเต็มไม่ใช่ขนาดเฉพาะ (ตรงกันข้ามกับภาษาเช่น Java และ C #)

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

ป้อน<cstdint>สิ่งที่จัดเตรียมอย่างแน่นอนและเป็นส่วนหัวมาตรฐานที่คอมไพเลอร์และแพลตฟอร์มไลบรารีมาตรฐานทั้งหมดจำเป็นต้องระบุ หมายเหตุ: ส่วนหัวนี้จำเป็นเฉพาะในฐานะของ C ++ 11 แต่มีการใช้งานไลบรารีรุ่นเก่าจำนวนมากที่จัดเตรียมไว้ให้

ต้องการจำนวนเต็ม 64 บิตที่ไม่ได้ลงชื่อ? uint64_tใช้ ลงทะเบียน 32 บิตเต็ม? int32_tใช้ ในขณะที่ประเภทในส่วนหัวเป็นตัวเลือก แต่แพลตฟอร์มที่ทันสมัยควรรองรับประเภททั้งหมดที่กำหนดไว้ในส่วนหัวนั้น

บางครั้งจำเป็นต้องใช้ความกว้างบิตเฉพาะเช่นในโครงสร้างข้อมูลที่ใช้สำหรับการสื่อสารกับระบบอื่น บางครั้งมันก็ไม่ได้ สำหรับสถานการณ์ที่เข้มงวดน้อยกว่า<cstdint>จัดเตรียมประเภทที่มีความกว้างต่ำสุด

มีตัวแปรน้อยที่สุด : int_leastXX_tจะเป็นประเภทจำนวนเต็มของบิต XX ขั้นต่ำ มันจะใช้ประเภทที่เล็กที่สุดที่ให้ XX บิต แต่ประเภทที่ได้รับอนุญาตให้มีขนาดใหญ่กว่าจำนวนบิตที่ระบุ ในทางปฏิบัติโดยทั่วไปแล้วสิ่งเหล่านี้จะเหมือนกับชนิดที่อธิบายข้างต้นที่ให้จำนวนบิตที่แน่นอน

นอกจากนี้ยังมีรูปแบบที่รวดเร็ว : int_fastXX_tมีอย่างน้อย XX บิต แต่ควรใช้ประเภทที่ทำงานได้อย่างรวดเร็วบนแพลตฟอร์มเฉพาะ คำจำกัดความของ "เร็ว" ในบริบทนี้ไม่ได้ระบุไว้ อย่างไรก็ตามในทางปฏิบัติสิ่งนี้มักหมายความว่าชนิดที่เล็กกว่าขนาดการลงทะเบียนของ CPU อาจใช้นามแฝงกับขนาดของขนาดการลงทะเบียนของ CPU ตัวอย่างเช่นส่วนหัวของ Visual C ++ 2015 ระบุว่าint_fast16_tเป็นจำนวนเต็ม 32 บิตเนื่องจากเลขคณิต 32 บิตโดยรวมจะเร็วขึ้นใน x86 มากกว่าเลขคณิต 16 บิต

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

ดังนั้นใช่longควรถูกห้ามจากรหัส C ++ ที่ทันสมัย ดังนั้นควรint, และshortlong long


20
ฉันหวังว่าฉันมีบัญชีอื่นอีกห้าบัญชีเพื่อลงคะแนนนี้อีกบางส่วน
Steven Burnap

4
+1 ฉันได้จัดการกับข้อผิดพลาดหน่วยความจำแปลก ๆ ที่เกิดขึ้นเมื่อขนาดของ struct ขึ้นอยู่กับคอมพิวเตอร์ที่คุณคอมไพล์
Joshua Snider

9
@Wildcard เป็นส่วนหัว C ที่เป็นส่วนหนึ่งของ C ++: ดูส่วนนำหน้า "c" นอกจากนี้ยังมีวิธีใส่ typedefs ในstdเนมสเปซเมื่อ#included ในหน่วยการคอมไพล์ C ++ แต่เอกสารที่ฉันเชื่อมโยงไม่ได้กล่าวถึงมันและ Visual Studio ดูเหมือนว่าจะไม่สนใจว่าฉันจะเข้าถึงมันอย่างไร

11
การแบนintอาจ ... มากเกินไป? (ฉันจะพิจารณาว่าถ้ารหัสจะต้องพกพาอย่างมากในทุกแพลตฟอร์ม (และไม่คลุมเครือ) ที่คลุมเครือการห้ามสำหรับ "รหัสแอป" อาจไม่ดีนักกับ devs ของเรา
Martin Ba

5
@Snowman #include <cstdint>ถูกต้องที่จะนำชนิดในstd::และ (น่าเศร้า) เลือกที่ได้รับอนุญาตนอกจากนี้ยังจะนำพวกเขาใน namespace โลก #include <stdint.h>เป็นสิ่งที่ตรงกันข้าม เช่นเดียวกับส่วนหัว C อื่น ๆ โปรดดู: stackoverflow.com/a/13643019/2757035ฉันหวังว่ามาตรฐานจะกำหนดให้แต่ละคนส่งผลกระทบต่อเนมสเปซที่ต้องการเท่านั้น - ดูเหมือนว่าจะลดน้อยลงไปสู่การประชุมที่น่าสงสารที่สร้างขึ้นโดยการใช้งานบางอย่าง - แต่ก็ดี
underscore_d

38

ไม่การห้ามประเภทจำนวนเต็มในตัวจะไร้สาระ อย่างไรก็ตามพวกเขาไม่ควรถูกทารุณกรรมเช่นกัน

หากคุณต้องการจำนวนเต็มว่าเป็นว่า ไม่มีบิตกว้างใช้(หรือถ้าคุณต้องการรุ่น) การคิดว่าเป็นจำนวนเต็ม 32 บิตและเป็นจำนวนเต็ม 64 บิตนั้นผิด อาจเป็นเช่นนี้ในแพลตฟอร์มปัจจุบันของคุณ แต่สิ่งนี้ขึ้นอยู่กับพฤติกรรมที่กำหนดโดยการนำไปใช้งานstd::intN_tstd::uintN_tunsignedintlong long

การใช้ชนิดจำนวนเต็มความกว้างคงที่ยังมีประโยชน์สำหรับการทำงานร่วมกันกับเทคโนโลยีอื่น ๆ ตัวอย่างเช่นหากบางส่วนของแอปพลิเคชันของคุณเขียนด้วย Java และอื่น ๆ ใน C ++ คุณอาจต้องการจับคู่ประเภทจำนวนเต็มเพื่อให้ได้ผลลัพธ์ที่สอดคล้องกัน (โปรดทราบว่าล้นใน Java มีความหมายที่กำหนดไว้อย่างดีในขณะที่signedล้นใน C ++ เป็นพฤติกรรมที่ไม่ได้กำหนดดังนั้นความสอดคล้องเป็นเป้าหมายสูง) พวกเขาจะมีค่าเมื่อการแลกเปลี่ยนข้อมูลระหว่างโฮสต์คอมพิวเตอร์ที่แตกต่างกัน

หากคุณไม่ต้องการบิตN ทุกประการ แต่เป็นประเภทที่กว้างพอให้ลองใช้(ปรับให้เหมาะกับพื้นที่) หรือ(ปรับให้เหมาะกับความเร็ว) อีกครั้งทั้งสองครอบครัวมีคู่เช่นกันstd::int_leastN_tstd::int_fastN_tunsigned

ดังนั้นเมื่อใดที่จะใช้ประเภท builtin? เนื่องจากมาตรฐานไม่ได้ระบุความกว้างอย่างแม่นยำให้ใช้เมื่อคุณไม่สนใจความกว้างบิตจริง แต่เกี่ยวกับลักษณะอื่น ๆ

A charเป็นจำนวนเต็มที่น้อยที่สุดที่ฮาร์ดแวร์สามารถระบุได้ ภาษาบังคับให้คุณใช้ภาษานั้นเพื่อลบล้างหน่วยความจำโดยพลการ นอกจากนี้ยังเป็นชนิดที่ใช้งานได้เท่านั้นสำหรับการแสดงสตริงอักขระ (แคบ)

intมักจะเป็นประเภทที่เร็วที่สุดเครื่องที่สามารถจัดการ มันจะกว้างพอที่จะสามารถโหลดและจัดเก็บด้วยคำสั่งเดียว (โดยไม่ต้องปิดบังหรือเปลี่ยนบิต) และแคบพอที่จะสามารถใช้งานได้กับคำแนะนำฮาร์ดแวร์ที่มีประสิทธิภาพ (ส่วนใหญ่) ดังนั้นจึงintเป็นตัวเลือกที่สมบูรณ์แบบสำหรับการส่งผ่านข้อมูลและการคำนวณทางคณิตศาสตร์เมื่อไม่ได้รับความกังวลมากเกินไป ยกตัวอย่างเช่นเริ่มต้นประเภทพื้นฐานของ enumerations intเป็น อย่าเปลี่ยนเป็นจำนวนเต็ม 32 บิตเพียงเพราะคุณทำได้ นอกจากนี้หากคุณมีค่าที่สามารถเป็น –1, 0 และ 1 เท่านั้นintเป็นตัวเลือกที่สมบูรณ์แบบเว้นแต่คุณจะเก็บอาร์เรย์ขนาดใหญ่ไว้ในกรณีนี้คุณอาจต้องการใช้ประเภทข้อมูลที่มีขนาดกะทัดรัดยิ่งขึ้นในราคาที่ต้องจ่ายในราคาที่สูงขึ้นสำหรับการเข้าถึงแต่ละองค์ประกอบ การแคชที่มีประสิทธิภาพมากขึ้นน่าจะชดเชยสิ่งเหล่านี้ได้ intการทำงานของระบบปฏิบัติการจำนวนมากมีการกำหนดไว้ยังอยู่ในแง่ของ มันจะไร้สาระที่จะแปลงการโต้แย้งและผลลัพธ์กลับไปกลับมา ทั้งหมดนี้สามารถทำได้คือการแนะนำข้อผิดพลาดมากเกินไป

longมักจะเป็นประเภทที่กว้างที่สุดที่สามารถจัดการได้ด้วยคำแนะนำเครื่องเดียว สิ่งนี้ทำให้unsigned longน่าสนใจอย่างยิ่งสำหรับการจัดการกับข้อมูลดิบและการจัดการบิตทุกชนิด ตัวอย่างเช่นฉันคาดหวังว่าจะเห็นunsigned longการใช้บิตเวกเตอร์ หากรหัสถูกเขียนอย่างระมัดระวังไม่สำคัญว่าขนาดนั้นกว้างแค่ไหน (เพราะรหัสจะปรับโดยอัตโนมัติ) บนแพลตฟอร์มที่ native machine-word คือ 32 บิตการมีอาร์เรย์สำรองของ bit-vector เป็นอาร์เรย์ของunsignedจำนวนเต็ม 32 บิตเป็นที่ต้องการมากที่สุดเพราะมันเป็นเรื่องโง่ที่จะใช้ชนิด 64 บิตที่จะต้องโหลดผ่านคำแนะนำที่มีราคาแพงเพียงเพื่อเปลี่ยนและปกปิดบิตที่ไม่จำเป็นออกไปอีกต่อไป ในทางกลับกันหากขนาดคำดั้งเดิมของแพลตฟอร์มเป็น 64 บิตฉันต้องการอาร์เรย์ประเภทนั้นเพราะหมายความว่าการดำเนินการเช่น "find first set" อาจทำงานเร็วเป็นสองเท่า ดังนั้น "ปัญหา" ของlongชนิดข้อมูลที่คุณกำลังอธิบายว่าขนาดของมันแตกต่างกันไปตามแต่ละแพลตฟอร์มจริง ๆ แล้วเป็นคุณลักษณะที่สามารถใช้งานได้ดี มันจะกลายเป็นปัญหาหากคุณคิดว่าประเภทบิวด์อินเป็นประเภทของความกว้างบิตที่แน่นอนซึ่งมันไม่ได้เป็น

char, intและlongเป็นชนิดที่มีประโยชน์มากตามที่อธิบายไว้ข้างต้น shortและlong longไม่ค่อยมีประโยชน์เท่าที่ควรเพราะความหมายของคำเหล่านั้นมีความชัดเจนน้อยกว่ามาก


4
OP เรียกโดยเฉพาะอย่างยิ่งความแตกต่างในขนาดlongระหว่าง Windows และ Unix ฉันอาจจะเข้าใจผิด แต่คำอธิบายของคุณเกี่ยวกับความแตกต่างของขนาดของlongการเป็น "ฟีเจอร์" แทนที่จะเป็น "ปัญหา" นั้นสมเหตุสมผลสำหรับฉันในการเปรียบเทียบตัวแบบข้อมูลขนาด 32 และ 64 บิต แต่ไม่ใช่สำหรับการเปรียบเทียบแบบนี้โดยเฉพาะ ในกรณีเฉพาะคำถามนี้ถามเกี่ยวกับนี่เป็นคุณสมบัติจริง ๆ หรือไม่ หรือเป็นคุณสมบัติในสถานการณ์อื่น ๆ (โดยทั่วไป) และไม่เป็นอันตรายในกรณีนี้หรือไม่?
Dan Getz

3
@ 5gon12eder: ปัญหาคือประเภทเช่น uint32_t ถูกสร้างขึ้นเพื่อวัตถุประสงค์ในการอนุญาตให้พฤติกรรมของโค้ดไม่ขึ้นอยู่กับขนาดของ "int" แต่การขาดประเภทที่มีความหมายจะเป็น "ประพฤติเหมือน uint32_t ทำงานบน 32- ระบบบิต "ทำให้การเขียนโค้ดที่มีพฤติกรรมไม่ถูกต้องตามขนาดของ" int "ยากกว่าการเขียนโค้ดที่เกือบจะถูกต้อง
supercat

3
ใช่ฉันรู้ว่า ... นั่นคือที่มาของคำสาป ผู้แต่งดั้งเดิมใช้เส้นทางของการต่อต้านการเช่าเพราะเมื่อพวกเขาเขียนรหัสระบบปฏิบัติการ 32- บิตนั้นอยู่ห่างออกไปหนึ่งทศวรรษ
Steven Burnap

8
@ 5gon12eder น่าเสียดายที่ supercat นั้นถูกต้อง ทุกชนิดที่แน่นอนความกว้างคือ "เพียง typedefs" โปรโมชั่นและกฎระเบียบจำนวนเต็มจะแจ้งให้ทราบของพวกเขาไม่ซึ่งหมายความว่าคณิตศาสตร์ในuint32_tค่าจะดำเนินการตามที่ได้ลงนาม , intคณิตศาสตร์กว้างบนแพลตฟอร์มที่intเป็นที่กว้างuint32_tกว่า (ด้วย ABIs ของวันนี้สิ่งนี้มีแนวโน้มที่จะเป็นประเด็นสำคัญสำหรับเรื่องนี้uint16_tอย่างมาก)
zwol

9
วันที่ 1 ขอบคุณสำหรับคำตอบอย่างละเอียด แต่: โอ้ที่รัก วรรคยาวของคุณ: " longมักจะเป็นประเภทที่กว้างที่สุดที่สามารถจัดการกับคำสั่งเครื่องเดี่ยว ... ." - และตรงนี้เป็นสิ่งที่ไม่ถูกต้อง ดูที่โมเดลข้อมูล Windows IMHO ตัวอย่างทั้งหมดต่อไปนี้ของคุณพังเพราะใน x64 Windows ที่มีความยาวยังคงเป็น 32 บิต
Martin Ba

6

คำตอบอีกข้อหนึ่งได้อธิบายเกี่ยวกับประเภท cstdint และรูปแบบที่รู้จักกันน้อยลงแล้ว

ฉันต้องการที่จะเพิ่มไปที่:

ใช้ชื่อประเภทเฉพาะโดเมน

นั่นคือไม่ได้ประกาศพารามิเตอร์และตัวแปรของคุณจะuint32_t(ไม่แน่นอนlong!) แต่ชื่อเช่นchannel_id_type, room_count_typeฯลฯ

เกี่ยวกับห้องสมุด

ไลบรารีของบุคคลที่สามที่ใช้longหรืออะไรก็ตามที่ไม่น่ารำคาญโดยเฉพาะอย่างยิ่งหากใช้เป็นข้อมูลอ้างอิงหรือตัวชี้ไปยังไลบรารีเหล่านั้น

ที่ดีที่สุดสิ่งที่จะทำให้การห่อ

โดยทั่วไปแล้วกลยุทธ์ของฉันคือการสร้างชุดฟังก์ชั่นแบบคาสต์ที่จะใช้ มีการรับข้อมูลมากเกินไปที่จะยอมรับเฉพาะประเภทที่ตรงกับประเภทที่เกี่ยวข้องพร้อมกับตัวชี้และรูปแบบอื่น ๆ ที่คุณต้องการ มีการกำหนดเฉพาะสำหรับระบบปฏิบัติการ / คอมไพเลอร์ / การตั้งค่า วิธีนี้ช่วยให้คุณลบคำเตือนและยังมั่นใจได้ว่ามีการใช้การแปลง "ขวา" เท่านั้น

channel_id_type cid_out;
...
SomeLibFoo (same_thing_really<int*>(&cid_out));

โดยเฉพาะอย่างยิ่งกับชนิดดั้งเดิมที่ต่างกันซึ่งผลิต 32 บิตตัวเลือกของคุณในการint32_tกำหนดอาจไม่ตรงกับการเรียกไลบรารี่ (เช่น int vs long บน Windows)

ฟังก์ชั่น cast-like เอกสารที่ขัดแย้งให้การตรวจสอบเวลาคอมไพล์ในผลลัพธ์ที่ตรงกับพารามิเตอร์ของฟังก์ชันและลบคำเตือนหรือข้อผิดพลาดใด ๆถ้าหากประเภทที่แท้จริงตรงกับขนาดจริงที่เกี่ยวข้อง นั่นคือมันมากเกินไปและกำหนดถ้าฉันผ่าน (บน Windows) int*หรือหรือlong*ให้ข้อผิดพลาดในการรวบรวมเวลาอื่น

ดังนั้นหากมีการอัปเดตห้องสมุดหรือมีคนเปลี่ยนแปลงสิ่งchannel_id_typeนี้จะยังคงได้รับการยืนยัน


ทำไม downvote (ไม่มีความคิดเห็น)
JDługosz

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