กฎเกี่ยวกับการใช้ขีดล่างในตัวระบุ C ++ คืออะไร?

Oct 23 2008

เป็นเรื่องปกติใน C ++ ที่จะตั้งชื่อตัวแปรสมาชิกด้วยคำนำหน้าบางประเภทเพื่อแสดงถึงความจริงที่ว่าเป็นตัวแปรสมาชิกแทนที่จะเป็นตัวแปรท้องถิ่นหรือพารามิเตอร์ หากคุณมาจากพื้นหลัง MFC คุณอาจใช้m_fooไฟล์. ฉันยังเคยเห็นmyFooเป็นครั้งคราว

ดูเหมือนว่า C # (หรืออาจเป็นเพียง. NET) จะแนะนำให้ใช้เพียงเครื่องหมายขีดล่างเช่นเดียวกับใน_foo. สิ่งนี้ได้รับอนุญาตตามมาตรฐาน C ++ หรือไม่?

คำตอบ

868 24revs,13users35%RogerPate Oct 23 2008 at 14:08

กฎ (ซึ่งไม่เปลี่ยนแปลงใน 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, และsetjmpva_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สัญลักษณ์ที่สงวนไว้จะถูกกำหนดไว้ที่นี่ ข้อ จำกัด ค่อนข้างเหมาะสมกว่าข้อ จำกัด ข้างต้น

202 paercebal Oct 23 2008 at 14:27

กฎเพื่อหลีกเลี่ยงการชนกันของชื่อมีทั้งในมาตรฐาน 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 หากไม่ได้กำหนดไว้ในเนมสเปซส่วนกลาง ...

40 RogerLipscombe Oct 23 2008 at 14:06

จากMSDN :

การใช้อักขระขีดล่างตามลำดับสองตัว (__) ที่จุดเริ่มต้นของตัวระบุหรือขีดล่างนำหน้าเดียวตามด้วยอักษรตัวใหญ่สงวนไว้สำหรับการใช้งาน C ++ ในทุกขอบเขต คุณควรหลีกเลี่ยงการใช้ขีดล่างนำหน้าตามด้วยอักษรตัวพิมพ์เล็กสำหรับชื่อที่มีขอบเขตไฟล์เนื่องจากอาจมีความขัดแย้งกับตัวระบุที่สงวนไว้ในปัจจุบันหรือในอนาคต

ซึ่งหมายความว่าคุณสามารถใช้ขีดล่างเดียวเป็นคำนำหน้าตัวแปรสมาชิกได้ตราบเท่าที่ตามด้วยอักษรตัวพิมพ์เล็ก

เห็นได้ชัดว่าสิ่งนี้นำมาจากมาตรา 17.4.3.1.2 ของมาตรฐาน C ++ แต่ฉันไม่พบแหล่งต้นฉบับสำหรับมาตรฐานออนไลน์แบบเต็ม

ดูคำถามนี้ด้วย

25 MaxLybbert Nov 15 2008 at 03:03

สำหรับส่วนอื่น ๆ ของคำถามเป็นเรื่องปกติที่จะใส่เครื่องหมายขีดล่างไว้ท้ายชื่อตัวแปรเพื่อไม่ให้ขัดแย้งกับสิ่งที่อยู่ภายใน

ฉันทำสิ่งนี้แม้กระทั่งในชั้นเรียนและเนมสเปซเพราะจากนั้นฉันต้องจำกฎเพียงข้อเดียว (เทียบกับ "ที่ท้ายชื่อในขอบเขตส่วนกลางและจุดเริ่มต้นของชื่อทุกที่")

1 JohnMillikin Oct 23 2008 at 14:05

ใช่ขีดล่างสามารถใช้ที่ใดก็ได้ในตัวระบุ ฉันเชื่อว่ากฎคือ az, AZ, _ ใด ๆ ในอักขระตัวแรกและ + 0-9 สำหรับอักขระต่อไปนี้

คำนำหน้าขีดล่างเป็นเรื่องปกติในรหัส C - ขีดล่างเดียวหมายถึง "ส่วนตัว" และโดยปกติขีดล่างคู่จะสงวนไว้สำหรับใช้โดยคอมไพลเลอร์