ฉันเห็นตัวแปรที่กำหนดด้วยประเภทนี้ แต่ฉันไม่รู้ว่ามันมาจากไหนหรือจุดประสงค์ของมันคืออะไร ทำไมไม่ใช้ int หรือไม่ได้ลงนาม int? (ประเภทที่ "คล้ายกัน" อื่น ๆ ล่ะ void_t ฯลฯ )
ฉันเห็นตัวแปรที่กำหนดด้วยประเภทนี้ แต่ฉันไม่รู้ว่ามันมาจากไหนหรือจุดประสงค์ของมันคืออะไร ทำไมไม่ใช้ int หรือไม่ได้ลงนาม int? (ประเภทที่ "คล้ายกัน" อื่น ๆ ล่ะ void_t ฯลฯ )
คำตอบ:
จากWikipedia
stdlib.h
และstddef.h
ไฟล์ส่วนหัวกำหนดประเภทข้อมูลที่เรียกว่าsize_t
1ซึ่งจะใช้เพื่อแสดงขนาดของวัตถุ ฟังก์ชันไลบรารีที่ใช้ขนาดคาดว่าจะเป็นประเภทsize_t
และตัวดำเนินการ sizeof จะประเมินเป็นsize_t
และประเมินผู้ประกอบการที่จะประเภทที่แท้จริงขึ้น
size_t
อยู่กับแพลตฟอร์ม เป็นความผิดพลาดที่พบบ่อยคือการสมมติsize_t
เป็นเช่นเดียวกับ int ไม่ได้ลงนามซึ่งสามารถนำไปสู่ข้อผิดพลาดของการเขียนโปรแกรม2โดยเฉพาะอย่างยิ่งเป็น 64 บิตสถาปัตยกรรมกลายเป็นที่แพร่หลายมากขึ้น
ประเภทและมาโครต่อไปนี้กำหนดไว้ในส่วนหัวมาตรฐาน
stddef.h
<snip>
size_t
ซึ่งเป็นประเภทจำนวนเต็มที่ไม่ได้ลงชื่อของผลลัพธ์ของตัวดำเนินการ sizeof
int
และunsigned int
ประเภทคือ 32 บิตในขณะที่ size_t คือ 64 บิต
ตามคำอธิบาย size_t บน en.cppreference.com size_t
กำหนดไว้ในส่วนหัวต่อไปนี้:
std::size_t
...
Defined in header <cstddef>
Defined in header <cstdio>
Defined in header <cstring>
Defined in header <ctime>
Defined in header <cwchar>
size_t
คือประเภทจำนวนเต็มที่ไม่ได้ลงชื่อของผลลัพธ์ของตัวดำเนินการ sizeof (ISO C99 มาตรา 7.17)
ตัวsizeof
ดำเนินการให้ขนาด (เป็นไบต์) ของตัวถูกดำเนินการซึ่งอาจเป็นนิพจน์หรือชื่อในวงเล็บของชนิด ขนาดถูกกำหนดจากประเภทของตัวถูกดำเนินการ ผลลัพธ์คือจำนวนเต็ม ค่าของผลลัพธ์คือการนำไปใช้งานและประเภท (ประเภทจำนวนเต็มที่ไม่ได้ลงชื่อ) คือsize_t
(ISO C99 มาตรา 6.5.3.4)
การพูดจริงsize_t
แสดงถึงจำนวนไบต์ที่คุณสามารถระบุได้ ในสถาปัตยกรรมสมัยใหม่ส่วนใหญ่ในช่วง 10-15 ปีที่ผ่านมานั้นมีขนาด 32 บิตซึ่งมีขนาดเท่ากับ int ที่ไม่ได้ลงนาม อย่างไรก็ตามเรากำลังย้ายไปใช้ที่อยู่ 64 บิตในขณะที่uint
ส่วนใหญ่จะอยู่ที่ 32 บิต(ไม่รับประกันขนาดในมาตรฐาน c ++) ในการสร้างรหัสของคุณที่ขึ้นอยู่กับขนาดหน่วยความจำแบบพกพาในสถาปัตยกรรมต่างๆคุณควรใช้ไฟล์size_t
. ตัวอย่างเช่นสิ่งต่างๆเช่นขนาดอาร์เรย์ควรใช้size_t
's เสมอ หากคุณดูที่คอนเทนเนอร์มาตรฐาน::size()
ผลตอบแทนเสมอ a size_t
.
โปรดทราบว่า Visual Studio มีตัวเลือกการคอมไพล์ที่สามารถตรวจสอบข้อผิดพลาดประเภทนี้ที่เรียกว่า "ตรวจหาปัญหาการพกพา 64 บิต"
ด้วยวิธีนี้คุณจะทราบได้เสมอว่าขนาดคือเท่าใดเนื่องจากชนิดเฉพาะเจาะจงสำหรับขนาด คำถามของตัวเองแสดงให้เห็นว่าอาจเป็นปัญหาได้: เป็นint
หรือunsigned int
? นอกจากนี้สิ่งที่เป็นขนาด ( short
, int
, long
ฯลฯ )?
เนื่องจากมีการกำหนดประเภทเฉพาะคุณจึงไม่ต้องกังวลเกี่ยวกับความยาวหรือการเซ็นชื่อ
คำจำกัดความที่แท้จริงสามารถพบได้ในไลบรารีอ้างอิง C ++ซึ่งระบุว่า:
ประเภท:
size_t
(ประเภทอินทิกรัลที่ไม่ได้ลงชื่อ)หัวข้อ:
<cstring>
size_t
สอดคล้องกับชนิดข้อมูลที่ส่งคืนโดยตัวดำเนินการภาษาsizeof
และกำหนดไว้ในไฟล์<cstring>
ไฟล์ส่วนหัว (ในกลุ่มอื่น ๆ ) เป็นชนิดอินทิกรัลที่ไม่ได้ลงชื่อใน
<cstring>
นั้นจะถูกใช้เป็นชนิดของพารามิเตอร์num
ในฟังก์ชั่นmemchr
,memcmp
,memcpy
,memmove
,memset
,strncat
,strncmp
,strncpy
และstrxfrm
ซึ่งในทุกกรณีจะใช้ในการระบุจำนวนสูงสุดของไบต์หรือตัวอักษรที่ฟังก์ชั่นที่มีการส่งผลกระทบต่อนอกจากนี้ยังใช้เป็นประเภทผลตอบแทนสำหรับ
strcspn
,strlen
,strspn
และstrxfrm
ขนาดผลตอบแทนและความยาว
ควรกำหนด size_t ไว้ในส่วนหัวของไลบรารีมาตรฐานของคุณ จากประสบการณ์ของฉันมันมักจะเป็นเพียงการพิมพ์ดีดเป็น int ที่ไม่ได้ลงนาม แม้ว่าประเด็นก็คือไม่จำเป็นต้องเป็น ประเภทเช่น size_t อนุญาตให้ผู้จำหน่ายไลบรารีมาตรฐานมีอิสระในการเปลี่ยนชนิดข้อมูลพื้นฐานหากเหมาะสมกับแพลตฟอร์ม หากคุณถือว่า size_t ไม่ได้ลงนาม int เสมอ (ผ่านการแคสต์ ฯลฯ ) คุณอาจประสบปัญหาในอนาคตหากผู้ขายของคุณเปลี่ยน size_t เป็นเช่นประเภท 64 บิต เป็นเรื่องอันตรายที่จะสมมติอะไรเกี่ยวกับสิ่งนี้หรือประเภทห้องสมุดอื่น ๆ ด้วยเหตุผลนี้
ฉันไม่คุ้นเคยกับการvoid_t
ยกเว้นเป็นผลมาจากการค้นหาของ Google (มันใช้ในห้องสมุดโดย Kiem-ษ์ Vo ที่ AT & T วิจัยvmalloc
- ฉันแน่ใจว่ามันใช้ในห้องสมุดอื่น ๆ เช่นกัน)
xxx_t typedefs ต่างๆใช้เพื่อสร้างนามธรรมประเภทหนึ่งจากการใช้งานที่แน่นอนเฉพาะเนื่องจากประเภทคอนกรีตที่ใช้สำหรับบางสิ่งอาจแตกต่างกันไปในแต่ละแพลตฟอร์ม ตัวอย่างเช่น:
Void_t
นามธรรมประเภทของตัวชี้ที่ส่งคืนโดยรูทีนvmalloc
ไลบรารีเนื่องจากถูกเขียนขึ้นเพื่อทำงานบนระบบที่กำหนด ANSI / ISO C ไว้ล่วงหน้าโดยที่void
อาจไม่มีคีย์เวิร์ด อย่างน้อยนั่นคือสิ่งที่ฉันคาดเดาwchar_t
บทคัดย่อประเภทที่ใช้สำหรับอักขระแบบกว้างเนื่องจากในบางระบบจะเป็นประเภท 16 บิตส่วนประเภทอื่นจะเป็นประเภท 32 บิตดังนั้นหากคุณเขียนโค้ดการจัดการอักขระแบบกว้างเพื่อใช้wchar_t
ประเภทแทนกล่าวunsigned short
ว่าโค้ดนั้นน่าจะพกพาไปยังแพลตฟอร์มต่างๆได้มากขึ้น
ในโปรแกรมมินิมัลลิสต์ที่size_t
คำจำกัดความไม่ได้โหลด "โดยบังเอิญ" ในบางโปรแกรมมี แต่ฉันยังต้องการใช้ในบางบริบท (เช่นเพื่อเข้าถึงstd::vector<double>
) ฉันจึงใช้บริบทนั้นเพื่อแยกประเภทที่ถูกต้อง ตัวอย่างเช่นtypedef std::vector<double>::size_type size_t
.
(ล้อมรอบด้วยnamespace {...}
ถ้าจำเป็นเพื่อให้ขอบเขต จำกัด )
สำหรับ "ทำไมไม่ใช้ int หรือไม่ได้ลงนาม int" เพียงเพราะมันมีความหมายมากกว่าที่จะไม่ มีเหตุผลในทางปฏิบัติที่สามารถพูดtypedef
d เป็นint
และอัพเกรดเป็นlong
รุ่นหลังได้โดยไม่ต้องมีใครเปลี่ยนรหัสแน่นอน แต่โดยพื้นฐานแล้วประเภทควรจะมีความหมาย เพื่อให้ง่ายขึ้นอย่างมากตัวแปรประเภทsize_t
จึงเหมาะสำหรับและใช้สำหรับซึ่งมีขนาดของสิ่งต่างๆเช่นเดียวกับtime_t
ที่เหมาะสำหรับการบรรจุค่าเวลา วิธีการนำไปใช้จริงควรเป็นงานของการนำไปใช้งาน เมื่อเทียบกับการเรียกทุกอย่างการint
ใช้ชื่อประเภทที่มีความหมายเช่นนี้จะช่วยชี้แจงความหมายและเจตนาของโปรแกรมของคุณเช่นเดียวกับชุดประเภทที่หลากหลาย