ฉันเห็นตัวแปรที่กำหนดด้วยประเภทนี้ แต่ฉันไม่รู้ว่ามันมาจากไหนหรือจุดประสงค์ของมันคืออะไร ทำไมไม่ใช้ int หรือไม่ได้ลงนาม int? (ประเภทที่ "คล้ายกัน" อื่น ๆ ล่ะ void_t ฯลฯ )
ฉันเห็นตัวแปรที่กำหนดด้วยประเภทนี้ แต่ฉันไม่รู้ว่ามันมาจากไหนหรือจุดประสงค์ของมันคืออะไร ทำไมไม่ใช้ int หรือไม่ได้ลงนาม int? (ประเภทที่ "คล้ายกัน" อื่น ๆ ล่ะ void_t ฯลฯ )
คำตอบ:
จากWikipedia
stdlib.hและstddef.hไฟล์ส่วนหัวกำหนดประเภทข้อมูลที่เรียกว่าsize_t1ซึ่งจะใช้เพื่อแสดงขนาดของวัตถุ ฟังก์ชันไลบรารีที่ใช้ขนาดคาดว่าจะเป็นประเภท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" เพียงเพราะมันมีความหมายมากกว่าที่จะไม่ มีเหตุผลในทางปฏิบัติที่สามารถพูดtypedefd เป็นintและอัพเกรดเป็นlongรุ่นหลังได้โดยไม่ต้องมีใครเปลี่ยนรหัสแน่นอน แต่โดยพื้นฐานแล้วประเภทควรจะมีความหมาย เพื่อให้ง่ายขึ้นอย่างมากตัวแปรประเภทsize_tจึงเหมาะสำหรับและใช้สำหรับซึ่งมีขนาดของสิ่งต่างๆเช่นเดียวกับtime_tที่เหมาะสำหรับการบรรจุค่าเวลา วิธีการนำไปใช้จริงควรเป็นงานของการนำไปใช้งาน เมื่อเทียบกับการเรียกทุกอย่างการintใช้ชื่อประเภทที่มีความหมายเช่นนี้จะช่วยชี้แจงความหมายและเจตนาของโปรแกรมของคุณเช่นเดียวกับชุดประเภทที่หลากหลาย