วิธีตรวจสอบว่ามีการกำหนดจำนวนเต็มความกว้างคงที่หรือไม่


25

ใน C ++ จำนวนเต็มความกว้างคงที่ถูกกำหนดเป็นทางเลือกแต่ฉันไม่สามารถหาวิธีที่แนะนำในการตรวจสอบว่ามีการกำหนดจริงหรือไม่

อะไรเป็นวิธีแบบพกพาในการตรวจสอบว่ามีจำนวนเต็มความกว้างคงที่หรือไม่


ดูเหมือนว่าจะไม่มีมาโครทดสอบคุณลักษณะแต่ฉันคิดว่าคุณสามารถทำได้#if defined(INT8_MIN)
Zereges

2
หากไลบรารี std ไม่ได้จัดเตรียมมาโครการทดสอบคุณลักษณะไว้คุณอาจตรวจสอบว่า toolchain ที่คุณใช้จัดเตรียมไว้หรือไม่หรืออนุญาตให้คุณกำหนดการทดสอบของตัวเอง ตัวอย่างเช่น CMake ช่วยให้คุณสามารถทดสอบคุณสมบัติภาษาบางอย่างโดยการรวบรวมcppไฟล์ที่กำหนดและขึ้นอยู่กับว่าการรวบรวมล้มเหลวหรือไม่แมโครที่คุณสามารถกำหนดได้
t.niese

หากคุณต้องการ autoconf เป็น cmake จะมีการทดสอบที่กำหนดไว้ล่วงหน้าสำหรับพวกเขา AC_TYPE_INT8_Tฯลฯ
Shawn

หากใครมีคะแนนแท็กใด ๆ ในstdint IMO cstdintควรได้รับการเสนอชื่อเป็นคำพ้องความหมาย ( stackoverflow.com/tags/stdint/synonyms ) ฉันไม่คิดว่าเราต้องการแท็ก C และ C ++ แยกกันสำหรับสิ่งที่คลุมเครือนี้ แท็กหลักของคำถามก็เพียงพอแล้ว
Peter Cordes

1
@PeterCordes มันทำงานในเวลานี้: stackoverflow.com/tags/stdint/synonyms
Andrew Henle

คำตอบ:


16

ในการตรวจสอบว่ามีการระบุประเภทจำนวนเต็มความกว้างคงที่คุณสามารถตรวจสอบว่ามีการกำหนดอย่างใดอย่างหนึ่งที่สอดคล้องกัน[U]INT*_MAXหรือ[U]INT*_MINแมโคร

// may be necessary for your C++ implementation
#define __STDC_LIMIT_MACROS 
#include <cstdint>

#ifdef INT32_MAX
// int32_t must be available to get here
int32_t some32bitIntVariable;
#endif

ต่อ7.20 ประเภท<stdint.h>เลขจำนวนเต็ม , ย่อหน้า 4 ของมาตรฐาน C11 (สังเกตส่วนที่เป็นตัวหนา):

สำหรับแต่ละประเภทอธิบายไว้ในที่นี้การดำเนินการให้<stdint.h>จะประกาศว่าtypedefชื่อและกำหนดมาโครที่เกี่ยวข้อง ตรงกันข้ามสำหรับแต่ละประเภทอธิบายไว้ในที่นี้การดำเนินการไม่ให้<stdint.h>จะไม่ประกาศว่าtypedefชื่อไม่เป็นมันจะกำหนดมาโครที่เกี่ยวข้อง

c ++ <cstdint>สืบทอดการดำเนินงานที่ผ่าน ดู<cstdint>vs<stdint.h>สำหรับรายละเอียดบางอย่าง ดูเพิ่มเติมทำอะไร__STDC_LIMIT_MACROSและ__STDC_CONSTANT_MACROSหมายถึงอะไร __STDC_LIMIT_MACROSสำหรับรายละเอียดเกี่ยวกับ

ดังนั้นหากint32_tสามารถใช้ได้INT32_MAXและINT32_MINจะต้องเป็น#define'd ตรงกันข้ามถ้าint32_tไม่สามารถใช้ได้ทั้งINT32_MAXมิได้INT32_MINรับอนุญาตให้เป็น#define'd

โปรดทราบว่าเนื่องจาก @NicolBolas ระบุไว้ในคำตอบอื่นอาจไม่จำเป็นต้องตรวจสอบจริง


มันจะสั้นกว่าในการตรวจสอบ[U]INT*_Cแทนมาโคร & min สูงสุด
phuclv

1
@phuclv ยกเว้นว่าไม่ใช่สิ่งเดียวกัน เช่นINT64_Cมีการกำหนดหากint64_least_tมีให้บริการหรือไม่ถ้าint64_tมี อ้างถึงเอกสารประกอบ
การแข่งขัน Lightness ใน Orbit

19

พูดกว้าง ... คุณทำไม่ได้

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

หากคุณไม่ต้องการจำนวนเต็มที่แน่นอน แต่เพียงต้องการเหตุผลอื่น ๆ ให้ใช้int_least_*ประเภท หากการใช้งานสามารถให้ขนาดตรงกับคุณleast_*ประเภทนั้นก็จะมีขนาดนั้น


4
สิ่งนี้ไม่เป็นความจริง ฉันได้เขียน stub passthroughs ที่ใช้ operator = / etc สำหรับแพลตฟอร์มที่ไม่รองรับ uint8_t มาก่อน แต่เพื่อประสิทธิภาพและจุดประสงค์ในการดีบั๊กคุณไม่ต้องการใช้สวิงเว้นแต่ว่าจำเป็นจริงๆ
TLW

@TLW: " ฉันเขียน stub passthroughs ที่ใช้โอเปอเรเตอร์ = / etc สำหรับแพลตฟอร์มที่ไม่รองรับ uint8_t มาก่อน " ตกลง แต่ ... ทำไม คุณเขียนโค้ดอะไรซึ่งต้องแน่ใจว่าไบต์คือ 8 บิต (ซึ่งน่าจะเป็นเหตุผลที่คุณใช้uint8_t) แต่รหัสนี้จำเป็นต้องใช้บนแพลตฟอร์มที่ไบต์ไม่ได้เป็น 8 บิต (ซึ่งนอกเหนือจากการใช้ การใช้งาน C ++ แบบเก่าจะเป็นเหตุผลเดียวที่ทำไมuint8_tจะไม่พร้อมใช้งาน) นั่นคือนอกเหนือจากความเข้ากันได้ย้อนหลังทำไมคุณต้องทำเช่นนี้?
Nicol Bolas

กรรมสิทธิ์ไม่สามารถพูดมากเกินไป codebase ที่ใช้ร่วมกันซึ่งจำเป็นต่อการสนับสนุนซึ่งเป็นสแต็กฮาร์ดแวร์ที่ค่อนข้างแปลกตา uint8_tมีความชัดเจนมากขึ้นกว่าวิธี ad-hoc (และ oft-broken) ก่อนหน้านี้
TLW

หากคุณมีอัลกอริทึมที่แสดงในรูปแบบของเช่นไบต์ 8 บิต passthrough เป็นสิ่งที่คุณสามารถเขียนได้ครั้งเดียวและง่ายต่อการทดสอบ ในขณะที่การแก้ไขทุกสถานที่เป็นแบบเฉพาะกิจและง่ายต่อการแก้ไขอย่างไม่ถูกต้อง O(1)เมื่อเทียบกับO(n)ความพยายาม uint16_tด้วยเหตุผลเดียวกันว่าทำไมคนใช้เช่น คุณกำลังถามว่า "ทำไมไม่ใช้ uint32_t แล้วโยนมันด้วยตัวเอง?" ซึ่งคำตอบควรชัดเจน
TLW

@TLW: "ด้วยเหตุผลเดียวกันว่าทำไมคนใช้เช่นuint16_t " นั่นไม่ใช่ของฉันuint16_tเหตุผลสำหรับการใช้ เหตุผลของฉันคือฉันกำลังสื่อสารกับอุปกรณ์ / รูปแบบ / อื่น ๆ ที่คาดว่าจะได้รับการจัดรูปแบบข้อมูล 16 บิตเป็นไบนารีจำนวนเต็มไม่ได้ลงนามโดยใช้ endian สำหรับเครื่องของฉันและถ้าฉันไม่สามารถรับประเภทที่แน่นอนว่าการสื่อสารอย่างมีประสิทธิภาพกับมันเป็นเรื่องยากมากขึ้น โปรแกรมของฉัน (และ API ที่ฉันใช้กับมัน) ไม่สามารถทำงานบนเครื่องที่ไม่ได้ใช้งาน
Nicol Bolas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.