กฎเกี่ยวกับการใช้ขีดล่างในตัวระบุ C ++ คืออะไร?
เป็นเรื่องปกติใน C ++ ที่จะตั้งชื่อตัวแปรสมาชิกด้วยคำนำหน้าบางประเภทเพื่อแสดงถึงความจริงที่ว่าเป็นตัวแปรสมาชิกแทนที่จะเป็นตัวแปรท้องถิ่นหรือพารามิเตอร์ หากคุณมาจากพื้นหลัง MFC คุณอาจใช้m_foo
ไฟล์. ฉันยังเคยเห็นmyFoo
เป็นครั้งคราว
ดูเหมือนว่า C # (หรืออาจเป็นเพียง. NET) จะแนะนำให้ใช้เพียงเครื่องหมายขีดล่างเช่นเดียวกับใน_foo
. สิ่งนี้ได้รับอนุญาตตามมาตรฐาน C ++ หรือไม่?
คำตอบ
กฎ (ซึ่งไม่เปลี่ยนแปลงใน C ++ 11):
- สงวนไว้ในขอบเขตใด ๆ รวมถึงเพื่อใช้เป็นมาโครการใช้งาน :
- ตัวระบุที่ขึ้นต้นด้วยขีดล่างตามด้วยอักษรตัวพิมพ์ใหญ่
- ตัวระบุที่มีขีดล่างติดกัน (หรือ "ขีดล่างคู่")
- สงวนไว้ในเนมสเปซส่วนกลาง:
- ตัวระบุที่ขึ้นต้นด้วยขีดล่าง
- นอกจากนี้ทุกอย่างใน
std
เนมสเปซจะถูกสงวนไว้ (คุณสามารถเพิ่มความเชี่ยวชาญพิเศษของเทมเพลตได้)
จากมาตรฐาน C ++ ปี 2003:
17.4.3.1.2 ชื่อสากล [lib.global.names]
ชื่อและลายเซ็นฟังก์ชันบางชุดจะสงวนไว้สำหรับการนำไปใช้งานเสมอ:
- ชื่อแต่ละชื่อที่มีเครื่องหมายขีดล่างคู่ (
__
) หรือขึ้นต้นด้วยขีดล่างตามด้วยอักษรตัวพิมพ์ใหญ่ (2.11) จะสงวนไว้สำหรับการนำไปใช้งานสำหรับการใช้งานใด ๆ- แต่ละชื่อที่ขึ้นต้นด้วยขีดล่างจะสงวนไว้สำหรับการนำไปใช้งานเพื่อใช้เป็นชื่อในเนมสเปซส่วนกลาง 165
165)ชื่อดังกล่าวถูกสงวนไว้ในเนมสเปซ
::std
(17.4.3.1)
เนื่องจาก C ++ เป็นไปตามมาตรฐาน C (1.1 / 2, C ++ 03) และ C99 เป็นการอ้างอิงเชิงบรรทัดฐาน (1.2 / 1, C ++ 03) สิ่งเหล่านี้ใช้จากมาตรฐาน 1999 C:
7.1.3 ตัวระบุที่สงวนไว้
แต่ละส่วนหัวจะประกาศหรือกำหนดตัวระบุทั้งหมดที่แสดงรายการในอนุประโยคที่เกี่ยวข้องและประกาศหรือกำหนดตัวระบุที่ระบุไว้ในคำสั่งย่อยและตัวระบุทิศทางไลบรารีในอนาคตที่เกี่ยวข้องซึ่งสงวนไว้เสมอสำหรับการใช้งานใด ๆ หรือเพื่อใช้เป็นตัวระบุขอบเขตไฟล์
- ตัวระบุทั้งหมดที่ขึ้นต้นด้วยขีดล่างและตัวอักษรตัวพิมพ์ใหญ่หรือขีดล่างอื่น ๆ จะถูกสงวนไว้สำหรับการใช้งานใด ๆ เสมอ
- ตัวระบุทั้งหมดที่ขึ้นต้นด้วยขีดล่างจะถูกสงวนไว้สำหรับใช้เป็นตัวระบุที่มีขอบเขตไฟล์ทั้งในช่องชื่อธรรมดาและชื่อแท็ก
- ชื่อแมโครแต่ละชื่อในอนุประโยคต่อไปนี้ (รวมถึงทิศทางไลบรารีในอนาคต) จะสงวนไว้สำหรับใช้ตามที่ระบุไว้หากมีส่วนหัวที่เกี่ยวข้องรวม เว้นแต่จะระบุไว้อย่างชัดเจนเป็นอย่างอื่น (ดู 7.1.4)
- ตัวระบุทั้งหมดที่มีการเชื่อมโยงภายนอกในอนุประโยคต่อไปนี้ (รวมถึงทิศทางไลบรารีในอนาคต) จะถูกสงวนไว้สำหรับใช้เป็นตัวระบุที่มีการเชื่อมโยงภายนอกเสมอ 154
- ตัวระบุแต่ละตัวที่มีขอบเขตไฟล์ที่แสดงอยู่ในอนุประโยคต่อไปนี้ (รวมถึงทิศทางไลบรารีในอนาคต) จะถูกสงวนไว้สำหรับใช้เป็นชื่อมาโครและเป็นตัวระบุที่มีขอบเขตไฟล์ในช่องว่างชื่อเดียวกันหากมีส่วนหัวที่เกี่ยวข้องใด ๆ รวมอยู่ด้วย
ไม่มีการสงวนตัวระบุอื่น ๆ หากโปรแกรมประกาศหรือกำหนดตัวระบุในบริบทที่สงวนไว้ (นอกเหนือจากที่อนุญาตโดย 7.1.4) หรือกำหนดตัวระบุที่สงวนไว้เป็นชื่อมาโครพฤติกรรมจะไม่ถูกกำหนด
หากโปรแกรมลบ (พร้อม
#undef
) นิยามมาโครของตัวระบุในกลุ่มแรกที่ระบุไว้ข้างต้นจะไม่ได้กำหนดลักษณะการทำงาน154)รายการของตัวระบุลิขสิทธิ์ที่มีการเชื่อมโยงภายนอกรวม
errno
,math_errhandling
, และsetjmp
va_end
อาจมีข้อ จำกัด อื่น ๆ ตัวอย่างเช่นมาตรฐาน POSIX สงวนตัวระบุจำนวนมากที่มีแนวโน้มว่าจะปรากฏในรหัสปกติ:
- ชื่อที่ขึ้นต้นด้วย
E
ตัวพิมพ์ใหญ่ตามด้วยตัวเลขหรือตัวอักษรตัวพิมพ์ใหญ่:- อาจใช้สำหรับชื่อรหัสข้อผิดพลาดเพิ่มเติม
- ชื่อที่ขึ้นต้นด้วยอักษรตัวพิมพ์เล็ก
is
หรือto
ตามด้วยตัวพิมพ์เล็ก- อาจใช้สำหรับการทดสอบอักขระเพิ่มเติมและฟังก์ชันการแปลง
- ชื่อที่ขึ้นต้นด้วย
LC_
อักษรตัวพิมพ์ใหญ่- อาจใช้สำหรับมาโครเพิ่มเติมที่ระบุแอตทริบิวต์โลแคล
- ชื่อของฟังก์ชันคณิตศาสตร์ที่มีอยู่ทั้งหมดที่ต่อท้าย
f
หรือl
สงวนไว้- สำหรับฟังก์ชันที่สอดคล้องกันซึ่งทำงานบนอาร์กิวเมนต์ลอยและอาร์กิวเมนต์คู่แบบยาวตามลำดับ
- ชื่อที่ขึ้นต้นด้วย
SIG
อักษรตัวพิมพ์ใหญ่จะถูกสงวนไว้- สำหรับชื่อสัญญาณเพิ่มเติม
- ชื่อที่ขึ้นต้นด้วย
SIG_
อักษรตัวพิมพ์ใหญ่จะถูกสงวนไว้- สำหรับการทำงานของสัญญาณเพิ่มเติม
- ชื่อขึ้นต้นด้วย
str
,mem
หรือwcs
ตามด้วยตัวอักษรตัวพิมพ์เล็กจะถูกสงวนไว้- สำหรับฟังก์ชันสตริงและอาร์เรย์เพิ่มเติม
- ชื่อที่ขึ้นต้นด้วย
PRI
หรือSCN
ตามด้วยอักษรตัวพิมพ์เล็กหรือX
สงวนไว้- สำหรับมาโครตัวระบุรูปแบบเพิ่มเติม
- ชื่อที่ลงท้ายด้วย
_t
สงวนไว้- สำหรับชื่อประเภทเพิ่มเติม
แม้ว่าการใช้ชื่อเหล่านี้เพื่อจุดประสงค์ของคุณเองในตอนนี้อาจไม่ก่อให้เกิดปัญหา แต่ก็เพิ่มความเป็นไปได้ที่จะขัดแย้งกับเวอร์ชันในอนาคตของมาตรฐานนั้น
โดยส่วนตัวฉันไม่ได้เริ่มตัวระบุด้วยเครื่องหมายขีดล่าง สิ่งใหม่เพิ่มเติมในกฎของฉัน: อย่าใช้เครื่องหมายขีดล่างคู่ที่ใดก็ได้ซึ่งเป็นเรื่องง่ายเพราะฉันไม่ค่อยใช้ขีดล่าง
หลังจากทำการค้นคว้าเกี่ยวกับบทความนี้ฉันไม่ได้สิ้นสุดตัวระบุของฉันอีกต่อไป_t
เนื่องจากถูกสงวนไว้โดยมาตรฐาน POSIX
กฎเกี่ยวกับตัวระบุใด ๆ ที่ลงท้ายด้วย_t
ทำให้ฉันประหลาดใจมาก ฉันคิดว่านั่นเป็นมาตรฐาน POSIX (ยังไม่แน่ใจ) กำลังมองหาคำชี้แจงและบทที่เป็นทางการและข้อ นี่มาจากคู่มือGNU libtoolรายชื่อที่สงวนไว้
CesarB ให้ลิงก์ต่อไปนี้ไปยังสัญลักษณ์และบันทึกที่สงวนไว้ของPOSIX 2004ซึ่งมีคำนำหน้าและคำต่อท้ายที่สงวนไว้มากมาย ... สามารถพบได้ที่นั่น ' POSIX 2008สัญลักษณ์ที่สงวนไว้จะถูกกำหนดไว้ที่นี่ ข้อ จำกัด ค่อนข้างเหมาะสมกว่าข้อ จำกัด ข้างต้น
กฎเพื่อหลีกเลี่ยงการชนกันของชื่อมีทั้งในมาตรฐาน C ++ (ดูหนังสือ Stroustrup) และกล่าวถึงโดยผู้เชี่ยวชาญด้าน C ++ (ซัตเทอร์ ฯลฯ )
กฎส่วนบุคคล
เนื่องจากฉันไม่ต้องการจัดการกับกรณีและต้องการกฎง่ายๆฉันจึงได้ออกแบบส่วนบุคคลที่ทั้งง่ายและถูกต้อง:
เมื่อตั้งชื่อสัญลักษณ์คุณจะหลีกเลี่ยงความขัดแย้งกับคอมไพเลอร์ / OS / ไลบรารีมาตรฐานหากคุณ:
- ห้ามขึ้นต้นสัญลักษณ์ด้วยเครื่องหมายขีดล่าง
- ห้ามตั้งชื่อสัญลักษณ์ที่มีขีดล่างติดกันสองอันด้านใน
แน่นอนว่าการใส่รหัสของคุณในเนมสเปซเฉพาะจะช่วยหลีกเลี่ยงการชนกันได้เช่นกัน (แต่จะไม่ป้องกันมาโครที่ชั่วร้าย)
ตัวอย่างบางส่วน
(ฉันใช้มาโครเพราะสัญลักษณ์ C / C ++ เป็นรหัสที่ก่อให้เกิดมลพิษมากขึ้น แต่อาจเป็นอะไรก็ได้ตั้งแต่ชื่อตัวแปรไปจนถึงชื่อคลาส)
#define _WRONG
#define __WRONG_AGAIN
#define RIGHT_
#define WRONG__WRONG
#define RIGHT_RIGHT
#define RIGHT_x_RIGHT
สารสกัดจากร่าง C ++ 0x
จากไฟล์n3242.pdf (ฉันคาดว่าข้อความมาตรฐานสุดท้ายจะคล้ายกัน):
17.6.3.3.2 ชื่อสากล [global.names]
ชื่อและลายเซ็นฟังก์ชันบางชุดจะสงวนไว้สำหรับการนำไปใช้งานเสมอ:
- แต่ละชื่อที่มีเครื่องหมายขีดล่างคู่ _ _ หรือขึ้นต้นด้วยขีดล่างตามด้วยตัวอักษรตัวพิมพ์ใหญ่ (2.12) จะถูกสงวนไว้สำหรับการนำไปใช้งานสำหรับการใช้งานใด ๆ
- แต่ละชื่อที่ขึ้นต้นด้วยขีดล่างจะสงวนไว้สำหรับการนำไปใช้งานเพื่อใช้เป็นชื่อในเนมสเปซส่วนกลาง
แต่ยัง:
17.6.3.3.5 คำต่อท้ายลิเทอรัลที่ผู้ใช้กำหนดเอง [usrlit.suffix]
ตัวระบุคำต่อท้ายตามตัวอักษรที่ไม่ได้ขึ้นต้นด้วยขีดล่างถูกสงวนไว้สำหรับการกำหนดมาตรฐานในอนาคต
ประโยคสุดท้ายนี้ทำให้สับสนเว้นแต่คุณจะพิจารณาว่าชื่อที่ขึ้นต้นด้วยเครื่องหมายขีดล่างหนึ่งตัวและตามด้วยอักษรตัวพิมพ์เล็กจะเป็น ok หากไม่ได้กำหนดไว้ในเนมสเปซส่วนกลาง ...
จากMSDN :
การใช้อักขระขีดล่างตามลำดับสองตัว (__) ที่จุดเริ่มต้นของตัวระบุหรือขีดล่างนำหน้าเดียวตามด้วยอักษรตัวใหญ่สงวนไว้สำหรับการใช้งาน C ++ ในทุกขอบเขต คุณควรหลีกเลี่ยงการใช้ขีดล่างนำหน้าตามด้วยอักษรตัวพิมพ์เล็กสำหรับชื่อที่มีขอบเขตไฟล์เนื่องจากอาจมีความขัดแย้งกับตัวระบุที่สงวนไว้ในปัจจุบันหรือในอนาคต
ซึ่งหมายความว่าคุณสามารถใช้ขีดล่างเดียวเป็นคำนำหน้าตัวแปรสมาชิกได้ตราบเท่าที่ตามด้วยอักษรตัวพิมพ์เล็ก
เห็นได้ชัดว่าสิ่งนี้นำมาจากมาตรา 17.4.3.1.2 ของมาตรฐาน C ++ แต่ฉันไม่พบแหล่งต้นฉบับสำหรับมาตรฐานออนไลน์แบบเต็ม
ดูคำถามนี้ด้วย
สำหรับส่วนอื่น ๆ ของคำถามเป็นเรื่องปกติที่จะใส่เครื่องหมายขีดล่างไว้ท้ายชื่อตัวแปรเพื่อไม่ให้ขัดแย้งกับสิ่งที่อยู่ภายใน
ฉันทำสิ่งนี้แม้กระทั่งในชั้นเรียนและเนมสเปซเพราะจากนั้นฉันต้องจำกฎเพียงข้อเดียว (เทียบกับ "ที่ท้ายชื่อในขอบเขตส่วนกลางและจุดเริ่มต้นของชื่อทุกที่")
ใช่ขีดล่างสามารถใช้ที่ใดก็ได้ในตัวระบุ ฉันเชื่อว่ากฎคือ az, AZ, _ ใด ๆ ในอักขระตัวแรกและ + 0-9 สำหรับอักขระต่อไปนี้
คำนำหน้าขีดล่างเป็นเรื่องปกติในรหัส C - ขีดล่างเดียวหมายถึง "ส่วนตัว" และโดยปกติขีดล่างคู่จะสงวนไว้สำหรับใช้โดยคอมไพลเลอร์