IMO ทำให้ฟังก์ชันมีขอบเขตของหน่วยการแปลเท่านั้น
อะไรคือความแตกต่างระหว่างฟังก์ชัน "static" และ "static inline"
ทำไมinline
ต้องใส่ไว้ในไฟล์ส่วนหัวไม่ใช่ใน.c
ไฟล์?
IMO ทำให้ฟังก์ชันมีขอบเขตของหน่วยการแปลเท่านั้น
อะไรคือความแตกต่างระหว่างฟังก์ชัน "static" และ "static inline"
ทำไมinline
ต้องใส่ไว้ในไฟล์ส่วนหัวไม่ใช่ใน.c
ไฟล์?
คำตอบ:
inline
สั่งให้คอมไพลเลอร์พยายามฝังเนื้อหาฟังก์ชันลงในโค้ดการเรียกแทนที่จะเรียกใช้งานจริง
สำหรับฟังก์ชั่นขนาดเล็กที่เรียกบ่อยซึ่งสามารถสร้างความแตกต่างด้านประสิทธิภาพได้มาก
อย่างไรก็ตามนี่เป็นเพียง "คำใบ้" และคอมไพเลอร์อาจเพิกเฉยและคอมไพเลอร์ส่วนใหญ่จะพยายาม "อินไลน์" แม้ว่าจะไม่ได้ใช้คีย์เวิร์ดก็ตามซึ่งเป็นส่วนหนึ่งของการเพิ่มประสิทธิภาพหากเป็นไปได้
ตัวอย่างเช่น:
static int Inc(int i) {return i+1};
.... // some code
int i;
.... // some more code
for (i=0; i<999999; i = Inc(i)) {/*do something here*/};
การวนซ้ำแบบแน่นนี้จะเรียกใช้ฟังก์ชันในการวนซ้ำแต่ละครั้งและเนื้อหาของฟังก์ชันนั้นน้อยกว่าโค้ดที่คอมไพลเลอร์ต้องใส่เพื่อทำการเรียก inline
โดยพื้นฐานแล้วจะสั่งให้คอมไพเลอร์แปลงโค้ดด้านบนให้เทียบเท่ากับ:
int i;
....
for (i=0; i<999999; i = i+1) { /* do something here */};
ข้ามการเรียกใช้ฟังก์ชันจริงและย้อนกลับ
เห็นได้ชัดว่านี่เป็นตัวอย่างเพื่อแสดงประเด็นไม่ใช่โค้ดจริง
static
หมายถึงขอบเขต ในภาษา C หมายความว่าฟังก์ชัน / ตัวแปรสามารถใช้ได้ภายในหน่วยการแปลเดียวกันเท่านั้น
static
(มีหรือไม่มีinline
) สามารถอยู่ในส่วนหัวได้อย่างสมบูรณ์แบบดูเหตุผลว่าทำไมไม่ เทมเพลตสำหรับ C ++ คำถามนี้เกี่ยวกับ C.
inline
จึงเป็นรูปแบบที่ดี imo
inline
ไม่ได้สั่งให้คอมไพเลอร์พยายามใด ๆ ในการซับใน เป็นเพียงการอนุญาตให้โปรแกรมเมอร์รวมเนื้อความฟังก์ชันไว้ในหน่วยการแปลหลายหน่วยโดยไม่ละเมิด ODR ผลข้างเคียงของสิ่งนี้คือทำให้คอมไพเลอร์เป็นไปได้เมื่อมันจะอินไลน์ฟังก์ชันจะทำสิ่งนี้ได้
ตามค่าเริ่มต้นคำจำกัดความแบบอินไลน์ใช้ได้เฉพาะในหน่วยการแปลปัจจุบัน
ถ้าคลาสหน่วยเก็บคือextern
ตัวระบุจะมีการเชื่อมโยงภายนอกและนิยามอินไลน์ยังให้นิยามภายนอกด้วย
ถ้าคลาสหน่วยเก็บคือstatic
ตัวระบุจะมีการเชื่อมโยงภายในและนิยามอินไลน์จะมองไม่เห็นในหน่วยการแปลอื่น
หากไม่ได้ระบุคลาสหน่วยเก็บข้อมูลนิยามแบบอินไลน์จะปรากฏในหน่วยการแปลปัจจุบันเท่านั้น แต่ตัวระบุยังคงมีการเชื่อมโยงภายนอกและต้องระบุนิยามภายนอกในหน่วยการแปลอื่น คอมไพลเลอร์มีอิสระที่จะใช้อินไลน์หรือนิยามภายนอกหากฟังก์ชันถูกเรียกใช้ภายในหน่วยการแปลปัจจุบัน
เนื่องจากคอมไพลเลอร์มีอิสระในการอินไลน์ (และไม่อยู่ในบรรทัด) ฟังก์ชันใด ๆ ที่มีความหมายที่มองเห็นได้ในหน่วยการแปลปัจจุบัน (และด้วยการเพิ่มประสิทธิภาพเวลาลิงก์แม้ในหน่วยการแปลที่แตกต่างกันแม้ว่ามาตรฐาน C จะไม่ได้คำนึงถึง นั้น) เพื่อวัตถุประสงค์ในทางปฏิบัติส่วนใหญ่ไม่มีความแตกต่างระหว่างstatic
และstatic inline
นิยามฟังก์ชัน
ตัวinline
ระบุ (เช่นregister
คลาสหน่วยเก็บข้อมูล) เป็นเพียงคำใบ้ของคอมไพเลอร์เท่านั้นและคอมไพเลอร์มีอิสระที่จะเพิกเฉยโดยสิ้นเชิง คอมไพเลอร์ที่ไม่ปรับให้เหมาะสมตามมาตรฐานจะต้องให้เกียรติผลข้างเคียงของมันเท่านั้นและการเพิ่มประสิทธิภาพคอมไพเลอร์จะทำการเพิ่มประสิทธิภาพเหล่านี้โดยมีหรือไม่มีคำใบ้ที่ชัดเจน
inline
และregister
ไม่ไร้ประโยชน์แม้ว่าจะสั่งให้คอมไพเลอร์โยนข้อผิดพลาดเมื่อโปรแกรมเมอร์เขียนโค้ดที่จะทำให้การปรับให้เหมาะสมเป็นไปไม่ได้: inline
นิยามภายนอกไม่สามารถอ้างอิงตัวระบุที่มีการเชื่อมโยงภายในได้ (เนื่องจากสิ่งเหล่านี้จะไม่สามารถใช้ได้ในหน่วยการแปลอื่น) หรือกำหนดตัวแปรภายในที่ปรับเปลี่ยนได้โดยมีระยะเวลาการจัดเก็บแบบคงที่ (เนื่องจากสิ่งเหล่านี้จะไม่แชร์สถานะกับหน่วยการแปล) และคุณไม่สามารถใช้ที่อยู่ของregister
ตัวแปรที่มีคุณสมบัติเหมาะสมได้
โดยส่วนตัวแล้วฉันใช้หลักการนี้เพื่อทำเครื่องหมายstatic
คำจำกัดความของฟังก์ชันภายในส่วนหัวด้วยinline
เนื่องจากเหตุผลหลักในการใส่คำจำกัดความของฟังก์ชันในไฟล์ส่วนหัวคือการทำให้ไม่สามารถใช้งานได้
โดยทั่วไปฉันใช้คำจำกัดความของstatic inline
ฟังก์ชันและstatic const
อ็อบเจ็กต์นอกเหนือจากการextern
ประกาศภายในส่วนหัวเท่านั้น
ฉันไม่เคยเขียนinline
ฟังก์ชันที่มีคลาสพื้นที่เก็บข้อมูลที่แตกต่างจากstatic
.
inline
ราวกับว่ามันถูกนำไปใช้กับการอินไลน์จริงๆนั้นทำให้เข้าใจผิดและเนื้อหาไม่ถูกต้อง ไม่มีคอมไพเลอร์ที่ทันสมัยใช้เป็นคำใบ้ในการอินไลน์หรือต้องการเพื่อเปิดใช้งานการแทรกในฟังก์ชัน
static
static inline
ทั้งสองทำให้ความหมายมองไม่เห็นในหน่วยการแปลอื่น ๆ อะไรคือเหตุผลที่สมเหตุสมผลที่จะเขียนstatic inline
แทนstatic
?
จากประสบการณ์ของฉันกับ GCC ฉันรู้static
และstatic inline
แตกต่างกันในวิธีที่คอมไพเลอร์ออกคำเตือนเกี่ยวกับฟังก์ชันที่ไม่ได้ใช้ แม่นยำมากขึ้นเมื่อคุณประกาศstatic
ฟังก์ชั่นและมันไม่ได้ถูกใช้ในหน่วยแปลปัจจุบันเตือนผลิตแล้วคอมไพเลอร์เกี่ยวกับฟังก์ชั่นที่ไม่ได้ใช้ static inline
แต่คุณสามารถยับยั้งการเตือนว่ามีการเปลี่ยนไป
ดังนั้นฉันมักคิดว่าstatic
ควรใช้ในหน่วยการแปลและได้รับประโยชน์จากคอมไพเลอร์ตรวจสอบพิเศษเพื่อค้นหาฟังก์ชันที่ไม่ได้ใช้ และstatic inline
ควรใช้ในไฟล์ส่วนหัวเพื่อจัดเตรียมฟังก์ชันที่สามารถเรียงกันได้ (เนื่องจากไม่มีการเชื่อมโยงภายนอก) โดยไม่ต้องออกคำเตือน
น่าเสียดายที่ฉันไม่พบหลักฐานใด ๆ สำหรับตรรกะนั้น แม้แต่จากเอกสาร GCC ฉันก็ไม่สามารถสรุปได้ว่าinline
ยับยั้งคำเตือนเกี่ยวกับฟังก์ชันที่ไม่ได้ใช้ ฉันจะขอบคุณถ้ามีคนแชร์ลิงก์ไปยังคำอธิบายนั้น
warning: unused function 'function' [clang-diagnostic-unused-function]
สำหรับstatic inline
ฟังก์ชันเมื่อสร้างด้วยclang-tidy
(v8.0.1) ซึ่งใช้ในหน่วยการแปลอื่น แต่แน่นอนว่านี่เป็นหนึ่งในคำอธิบายและเหตุผลที่ดีที่สุดในการรวมstatic
& inline
!
ใน C static
หมายถึงฟังก์ชันหรือตัวแปรที่คุณกำหนดสามารถใช้ได้เฉพาะในไฟล์นี้ (เช่นหน่วยคอมไพล์)
ดังนั้นstatic inline
หมายถึงฟังก์ชันอินไลน์ที่สามารถใช้ได้ในไฟล์นี้เท่านั้น
แก้ไข:
หน่วยคอมไพล์ควรเป็นหน่วยการแปล
the compile unit
เป็นสิ่งที่ฉันเขียนด้วยความผิดพลาดไม่มีสิ่งนั้นคำศัพท์ที่แท้จริงคือtranslation unit
ความแตกต่างอย่างหนึ่งที่ไม่ได้อยู่ที่ระดับภาษา แต่เป็นระดับการนำไปใช้งานที่ได้รับความนิยม: gcc บางเวอร์ชันจะลบstatic inline
ฟังก์ชันที่ไม่ได้อ้างอิงออกจากเอาต์พุตตามค่าเริ่มต้น แต่จะยังคงใช้static
ฟังก์ชันธรรมดาแม้ว่าจะไม่ได้อ้างอิงก็ตาม ฉันไม่แน่ใจว่ารุ่นนี้ แต่จากมุมมองในทางปฏิบัติมันหมายความว่ามันอาจจะเป็นความคิดที่ดีที่จะมักจะใช้inline
สำหรับstatic
ฟังก์ชั่นในส่วนหัว
inline
คำจำกัดความล่ะ? คุณไม่ได้ใช้มันเพื่อextern
ฟังก์ชั่นหรือไม่?
attribute((used))
และการใช้งานเพื่ออนุญาตให้ asm อ้างอิงstatic
ฟังก์ชันและข้อมูลที่ไม่ได้อ้างอิงเป็นอย่างอื่น
static
หมายถึงขอบเขต ในภาษา C หมายความว่าฟังก์ชัน / ตัวแปรสามารถใช้ได้ภายในหน่วยการแปลเดียวกันเท่านั้น