การใช้มาโคร C / C ++ เป็นทางลัดสำหรับการคอมไพล์แบบมีเงื่อนไขหรือไม่?


13

สมมติว่าฉันต้องการมีข้อความเอาต์พุตหลายประเภทในรหัสของฉัน หนึ่งในนั้นคือDEBUGซึ่งจะถูกพิมพ์เท่านั้นเมื่อรวบรวมรหัสในโหมด Debug

โดยปกติฉันจะต้องเขียนบางอย่างเช่น

#ifdef DEBUG
    std::cout << "Debug message" << std::endl;
#endif

ซึ่งค่อนข้างยุ่งยากและน่ารำคาญในหลาย ๆ ที่

เป็นวิธีปฏิบัติที่ดีในการกำหนดแมโครสำหรับข้อมูลโค้ดดังนั้นคุณจะใช้วิธีนี้หรือไม่

MSG_DEBUG("Debug message")

หรือมีวิธีอื่นที่สวยงามกว่าวิธีจัดการกับมันโดยไม่มีมาโคร ฉันสนใจโซลูชันที่เป็นไปได้ทั้งใน C และ C ++ เนื่องจากฉันใช้ทั้งสองภาษาในโครงการที่แตกต่างกัน



มันยังไม่ชัดเจนจากคำถามที่ว่าทำไมคุณไม่ใส่โค้ดที่มีเงื่อนไขลงในฟังก์ชันแล้วเรียกมันว่า มีข้อ จำกัด อื่น ๆ ที่จะป้องกันไม่ให้?
อเล็กซ์

@gnat คำถามที่คุณพูดถึงนั้นกว้างมากจนคนส่วนใหญ่จะไม่เชื่อมต่อกับหัวข้อนี้โดยเฉพาะเมื่อพวกเขาต้องการค้นหาคำถามเฉพาะนี้ทางอินเทอร์เน็ต
Eenoku

3
คำถามของคุณถูกแท็กด้วยทั้งcและc ++อย่างไรก็ตามคำถามเหล่านี้เป็นภาษาที่แตกต่างกันมาก คุณช่วยอธิบายสิ่งที่คุณกำลังพูดถึงได้หรือไม่? ตัวอย่างของคุณน่าจะใช้ได้ดีใน C แต่อาจนำไปใช้กับ a constexpr if++ ได้ดีกว่า
Jörg W Mittag

1
STDERRเช่นกันการวินิจฉัยควรจะไป นอกจากนี้ทำไมไม่ทำให้มันขึ้นอยู่กับNDEBUGว่าชอบassert()แทน? จากนั้นคุณสามารถกำหนดเช่น#define DEBUG_MSG(MSG) assert(std::cerr << MSG)นี้ซึ่งทดสอบสถานะกระแสด้วย
Deduplicator

คำตอบ:


19

แน่นอนว่าถ้าคุณโอเคกับการใช้มาโครในตอนแรกการกำหนดพารามิเตอร์แบบ Parametrized แทนที่จะทำซ้ำรหัสที่มีเงื่อนไขเดียวกันนั้นจะดีกว่าหากใช้การเข้ารหัสที่ดี

คุณควรใช้มาโครหรือไม่? ในมุมมองของฉันคุณควรเนื่องจากเป็นวิธีปฏิบัติที่ยอมรับใน C และวิธีแก้ปัญหาแมโครน้อยใด ๆ จะต้องมีสิ่งที่ถูกดำเนินการอย่างน้อยแม้อยู่นอกโหมดดีบัก โปรแกรมเมอร์ C ทั่วไปจะเลือกมาโครที่น่าเกลียดกว่าความพยายามที่ไม่จำเป็นในเวลาใดก็ได้


13

มีองค์ประกอบของการตั้งค่าส่วนตัวที่นี่ แต่ใน C ++ ฉันชอบที่จะทำในไฟล์ส่วนหัว:

#ifdef _DEBUG
    void DebugMessage(...);
#else
    inline void DebugMessage(...) {}
#endif

เพื่อให้ฟังก์ชั่น inlined เก็บไว้ใน build build แต่เป็นฟังก์ชั่นที่เหมาะสมใน debug build ดังนั้นคุณสามารถตรวจสอบประเภทที่เหมาะสมข้อความแสดงข้อผิดพลาดที่สมเหตุสมผล ฯลฯ และความสามารถในการเพิ่มฟังก์ชันการทำงานอื่น ๆ

เห็นได้ชัดว่าคุณต้องเข้ารหัสข้อกำหนดที่เกี่ยวข้องของฟังก์ชันใน.cppไฟล์ใน#ifdef _DEBUGบล็อก


แต่ค่าใช้จ่ายในการโทรยังคงอยู่ที่นี่ใช่ไหม?
Eenoku

7
หากคอมไพเลอร์ของคุณจะสร้างรหัสเพื่อเรียกใช้ฟังก์ชันว่างที่รู้จักในรุ่นบิลด์สิ่งแรกและสิ่งที่ใหญ่ที่สุดที่คุณต้องทำเพื่อปรับปรุงประสิทธิภาพคือรับคอมไพเลอร์ที่ดีกว่ามาก นี่คือการเพิ่มประสิทธิภาพเล็กน้อย
David Thornley

@Eenoku No ดังที่ David กล่าวไว้คอมไพเลอร์ใด ๆ ที่คุณควรใช้
Jack Aidley

3
มีความแตกต่างที่สำคัญที่นี่: แมโคร (ขึ้นอยู่กับวิธีการเขียน) จะไม่ประเมินการแสดงออกของอาร์กิวเมนต์ในขณะที่ฟังก์ชั่นจะเสมอ นอกจากนี้ยังมีพฤติกรรมที่ไม่ได้กำหนดไว้เพื่อส่งผ่านข้อโต้แย้งที่ไม่สำคัญไปยังฟังก์ชัน varargs (และมักจะทำให้เกิดคำเตือนคอมไพเลอร์)
Sebastian Redl


2

แน่นอนว่าให้แน่ใจว่าคุณไม่ได้ทำตามแนวทางของโค้ดที่ทีมของคุณกำหนด ตรวจสอบให้แน่ใจว่าไม่มีรหัสอื่นในระบบพยายามเข้าถึงฟังก์ชันการทำงานเดียวกันผ่านทางทั่วไปหากมีเงื่อนไข

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.