ฉันใช้ ints ที่ไม่ได้ลงชื่อเพื่อทำให้รหัสของฉันและเจตนาชัดเจนยิ่งขึ้น สิ่งหนึ่งที่ฉันทำเพื่อป้องกันการแปลงโดยนัยที่ไม่คาดคิดเมื่อทำเลขคณิตที่มีทั้งประเภทที่ลงชื่อและไม่ได้ลงชื่อคือการใช้ชื่อย่อที่ไม่ได้ลงชื่อ (โดยปกติ 2 ไบต์) สำหรับตัวแปรที่ไม่ได้ลงนาม สิ่งนี้มีประสิทธิภาพด้วยเหตุผลสองสามประการ:
- เมื่อคุณใช้เลขคณิตกับตัวแปรย่อที่ไม่ได้ลงชื่อและตัวอักษร (ซึ่งเป็นประเภท int) หรือตัวแปรของประเภท int สิ่งนี้ทำให้มั่นใจได้ว่าตัวแปรที่ไม่ได้ลงนามจะได้รับการเลื่อนระดับเป็นเสมอก่อนที่จะประเมินนิพจน์เนื่องจาก int มีอันดับสูงกว่าสั้นเสมอ . สิ่งนี้จะช่วยหลีกเลี่ยงพฤติกรรมที่ไม่คาดคิดใด ๆ ในการคำนวณทางคณิตศาสตร์ด้วยประเภทที่เซ็นชื่อและไม่ได้ลงนามโดยสมมติว่าผลลัพธ์ของนิพจน์เหมาะสมกับการลงทะเบียน int แน่นอน
- ส่วนใหญ่แล้วตัวแปรที่ไม่ได้ลงนามที่คุณใช้จะไม่เกินค่าสูงสุดของ short-byte ที่ไม่ได้ลงชื่อ 2 ตัว (65,535)
หลักการทั่วไปคือประเภทของตัวแปรที่ไม่ได้ลงนามของคุณควรมีอันดับต่ำกว่าประเภทของตัวแปรที่ลงนามเพื่อให้แน่ใจว่าการเลื่อนระดับเป็นประเภทที่เซ็นชื่อ จากนั้นคุณจะไม่มีพฤติกรรมล้นเกินคาด เห็นได้ชัดว่าคุณไม่สามารถมั่นใจได้ตลอดเวลา แต่ส่วนใหญ่มักจะเป็นไปได้ที่จะมั่นใจได้
ตัวอย่างเช่นเมื่อเร็ว ๆ นี้ฉันมีห่วงบางอย่างเช่นนี้
const unsigned short cuint = 5;
for(unsigned short i=0; i<10; ++i)
{
if((i-2)%cuint == 0)
{
//Do something
}
}
ตัวอักษร '2' เป็นประเภท int หากฉันเป็น int ที่ไม่ได้ลงนามแทนที่จะเป็น short short ที่ไม่ได้ลงชื่อดังนั้นในนิพจน์ย่อย (i-2), 2 จะได้รับการเลื่อนระดับเป็น int ที่ไม่ได้ลงนาม (เนื่องจาก int ที่ไม่ได้ลงชื่อมีลำดับความสำคัญสูงกว่า int ที่ลงนามแล้ว) ถ้า i = 0 ดังนั้นนิพจน์ย่อยจะเท่ากับ (0u-2u) = ค่าที่มากเนื่องจากการล้น แนวคิดเดียวกันกับ i = 1 อย่างไรก็ตามเนื่องจาก i เป็นคำย่อที่ไม่ได้ลงชื่อจึงได้รับการเลื่อนระดับเป็นประเภทเดียวกับตัวอักษร '2' ซึ่งลงนาม int และทุกอย่างทำงานได้ดี
เพื่อความปลอดภัยที่เพิ่มขึ้น: ในกรณีที่ไม่ค่อยเกิดขึ้นซึ่งสถาปัตยกรรมที่คุณใช้งานอยู่ทำให้เกิด int เป็น 2 ไบต์สิ่งนี้อาจทำให้ตัวถูกดำเนินการทั้งสองในนิพจน์ทางคณิตศาสตร์ได้รับการเลื่อนตำแหน่งให้เป็น int ที่ไม่ได้ลงชื่อในกรณีที่ตัวแปรสั้น ลงใน int 2-byte ที่ลงชื่อแล้วซึ่งส่วนหลังมีค่าสูงสุด 32,767 <65,535 (ดูhttps://stackoverflow.com/questions/17832815/c-implicit-conversion-signed-unsignedสำหรับรายละเอียดเพิ่มเติม) เพื่อป้องกันสิ่งนี้คุณสามารถเพิ่ม static_assert เข้ากับโปรแกรมของคุณดังนี้:
static_assert(sizeof(int) == 4, "int must be 4 bytes");
และมันจะไม่คอมไพล์ในสถาปัตยกรรมที่ int คือ 2 ไบต์
for(unsigned int n = 10; n >= 0; n --)
(ลูปอนันต์)