ในหลายภาษา C ++ ตัวอย่างที่ผมเห็นการใช้งานของประเภทที่ที่ฉันจะได้ใช้ง่ายๆsize_t
int
ความแตกต่างคืออะไรและทำไมจึงsize_t
ควรดีกว่า
ในหลายภาษา C ++ ตัวอย่างที่ผมเห็นการใช้งานของประเภทที่ที่ฉันจะได้ใช้ง่ายๆsize_t
int
ความแตกต่างคืออะไรและทำไมจึงsize_t
ควรดีกว่า
คำตอบ:
ไฟล์ส่วนหัว stdlib.h และ stddef.h กำหนดประเภทข้อมูลที่เรียกว่าsize_tซึ่งใช้เพื่อแสดงขนาดของวัตถุ ฟังก์ชั่นห้องสมุดที่ใช้ขนาดคาดว่าพวกเขาจะเป็นประเภท size_t และผู้ประกอบการ sizeof ประเมินเป็น size_t
ขนาดจริงของ size_t ขึ้นอยู่กับแพลตฟอร์ม ข้อผิดพลาดทั่วไปคือสมมติว่า size_t เป็น int ที่ไม่ได้ลงนามซึ่งสามารถนำไปสู่ข้อผิดพลาดในการเขียนโปรแกรมโดยเฉพาะอย่างยิ่งเมื่อสถาปัตยกรรม 64- บิตกลายเป็นที่แพร่หลายมากขึ้น
ตรวจสอบด้วยเหตุใดจึงยังมีปัญหาเรื่อง size_t
/usr/include/stdlib.h
ได้รับคำนิยามจาก/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h
นั้นมันเริ่มต้นlong unsigned int
เว้นแต่ไฟล์ส่วนหัวอื่น ๆ พูดอย่างอื่น
size_t เป็นประเภทที่ใช้ในการแสดงขนาด (ตามชื่อของมันหมายถึง) แพลตฟอร์ม (และอาจมีการนำไปใช้) ขึ้นอยู่กับแพลตฟอร์มและควรใช้เพื่อจุดประสงค์นี้เท่านั้น เห็นได้ชัดว่าเป็นขนาด size_t ไม่ได้ลงนาม ฟังก์ชั่น stdlib จำนวนมากรวมถึง malloc, sizeof และฟังก์ชั่นการทำงานของสตริงต่างๆใช้ size_t เป็นประเภทข้อมูล
int จะถูกลงนามโดยค่าเริ่มต้นและแม้ว่าขนาดของมันจะขึ้นอยู่กับแพลตฟอร์มก็ตามมันจะเป็น 32 บิตคงที่ในเครื่องที่ทันสมัยที่สุด
ในการสรุป: ใช้ size_t เพื่อแสดงขนาดของวัตถุและ int (หรือยาว) ในกรณีอื่น ๆ
size_t
ประเภทถูกกำหนดให้เป็นประเภทหนึ่งได้รับการรับรองของsizeof
ผู้ประกอบการ ในโลกแห่งความเป็นจริงคุณมักจะเห็นการint
กำหนดเป็น 32 บิต (สำหรับความเข้ากันได้ย้อนหลัง) แต่size_t
ถูกกำหนดเป็น 64 บิต (ดังนั้นคุณสามารถประกาศอาร์เรย์และโครงสร้างที่มีขนาดมากกว่า 4 GiB) บนแพลตฟอร์ม 64 บิต หาก a long int
คือ 64- บิตสิ่งนี้เรียกว่าการประชุม LP64 ถ้าlong int
เป็น 32 บิต แต่พlong long int
อยน์เตอร์เป็น 64 บิตนั่นคือ LLP64 นอกจากนี้คุณยังอาจได้รับการย้อนกลับโปรแกรมที่ใช้คำแนะนำ 64 บิตสำหรับความเร็ว แต่ตัวชี้แบบ 32 บิตเพื่อบันทึกหน่วยความจำ นอกจากนี้ยังint
มีการเซ็นชื่อและsize_t
ไม่ได้ลงนาม
นอกจากนั้นในอดีตจำนวนของแพลตฟอร์มอื่น ๆ int
ที่มีอยู่มีความกว้างขึ้นหรือสั้นกว่าขนาดของพื้นเมือง ในความเป็นจริงในยุค 70 และต้นยุค 80 นี่เป็นเรื่องธรรมดามากกว่า: คอมพิวเตอร์ 8 บิตที่ได้รับความนิยมทั้งหมดมีการลงทะเบียน 8 บิตและที่อยู่ 16 บิตและการเปลี่ยนระหว่าง 16 และ 32 บิตยังผลิตเครื่องจักรจำนวนมาก มีที่อยู่ที่กว้างกว่าการลงทะเบียน ฉันยังคงเห็นคำถามเกี่ยวกับ Borland Turbo C สำหรับ MS-DOS ที่มีโหมดหน่วยความจำขนาดใหญ่ซึ่งมีที่อยู่ 20 บิตที่เก็บไว้ใน 32 บิตบน CPU 16 บิต (แต่สามารถรองรับชุดคำสั่งแบบ 32 บิตของ 80386); Motorola 68000 มี ALU 16 บิตพร้อมการลงทะเบียนและที่อยู่ 32 บิต มีเมนเฟรมของ IBM พร้อมที่อยู่ 15 บิต 24 บิตหรือ 31 บิต คุณยังคงเห็น ALU และขนาดบัสที่แตกต่างกันในระบบฝังตัว
เมื่อใดก็ตามที่int
มีขนาดเล็กกว่าsize_t
และคุณพยายามจัดเก็บขนาดหรือออฟเซ็ตของไฟล์หรือวัตถุที่มีขนาดใหญ่มากในunsigned int
นั้นมีความเป็นไปได้ที่มันจะล้นและทำให้เกิดข้อผิดพลาด ด้วยความint
สามารถในการรับจำนวนลบ ถ้ามีint
หรือunsigned int
กว้างกว่าโปรแกรมจะทำงานอย่างถูกต้อง แต่หน่วยความจำไม่เพียงพอ
โดยทั่วไปคุณควรใช้ประเภทที่ถูกต้องเพื่อวัตถุประสงค์หากคุณต้องการพกพา ผู้คนจำนวนมากจะแนะนำให้คุณใช้คณิตศาสตร์ที่ลงนามแทนการไม่ได้ลงชื่อ (เพื่อหลีกเลี่ยงข้อบกพร่องที่น่ารังเกียจและบอบบางเช่น1U < -3
) เพื่อที่การกำหนดมาตรฐานห้องสมุดptrdiff_t
ใน<stddef.h>
เป็นชนิดลงนามในผลการลบตัวชี้จากผู้อื่น
วิธีแก้ปัญหาอาจเป็นการตรวจสอบที่อยู่และการหักล้างทั้งหมดINT_MAX
และอย่างใดอย่างหนึ่ง0
หรือINT_MIN
ตามความเหมาะสมและเปิดคำเตือนคอมไพเลอร์เกี่ยวกับการเปรียบเทียบปริมาณที่ลงชื่อและไม่ได้ลงชื่อในกรณีที่คุณพลาด คุณควรตรวจสอบการเข้าถึงอาร์เรย์ของคุณใน C เสมอ
เป็นเพราะ size_t สามารถเป็นอย่างอื่นได้นอกจาก int (อาจเป็น struct) แนวคิดก็คือมันแยกงานของมันออกจากประเภทพื้นฐาน
size_t
ระบุเป็นประเภทจำนวนเต็มไม่ได้ลงนาม C11 §6.5.3.4 5 "ค่าของผลลัพธ์ของตัวดำเนินการทั้งสอง ( sizeof
_Alignof
) คือการกำหนดการนำไปใช้และประเภทของมัน (ชนิดจำนวนเต็มที่ไม่ได้ลงนาม) คือsize_t
"
คำจำกัดความของSIZE_T
พบได้ที่:
https://msdn.microsoft.com/en-us/library/cc441980.aspxและhttps://msdn.microsoft.com/en-us/library/cc230394.aspx
การวางข้อมูลที่ต้องการที่นี่:
SIZE_T
เป็นULONG_PTR
จำนวนสูงสุดของไบต์ที่ตัวชี้สามารถชี้
ประเภทนี้มีการประกาศดังนี้:
typedef ULONG_PTR SIZE_T;
A ULONG_PTR
เป็นแบบยาวที่ไม่ได้ลงนามที่ใช้สำหรับความแม่นยำของตัวชี้ มันถูกใช้เมื่อชี้ตัวชี้ไปยังชนิดยาวเพื่อดำเนินการทางคณิตศาสตร์ตัวชี้
ประเภทนี้มีการประกาศดังนี้:
typedef unsigned __int3264 ULONG_PTR;
SIZE_T
ไม่ใช่size_t
สิ่งที่ OP ถามเกี่ยวกับ
SIZE_T
size_t
จะแตกต่างจาก SIZE_T
คุณไม่สามารถประกาศตัวแปรของชนิด