บล็อก #if 0 … #endif ทำหน้าที่อะไร


124

ในC / C ++

เกิดอะไรขึ้นกับรหัสที่วางระหว่าง#if 0/ #endifบล็อก

#if 0

//Code goes here

#endif

โค้ดถูกข้ามไปและไม่ถูกเรียกใช้งานใช่หรือไม่?


17
นี่เป็นเทคนิคที่ใช้ในการแสดงความคิดเห็นของโค้ดจำนวนมากหรือเพื่อให้สามารถทดสอบการรวมบล็อกของโค้ดได้ โดยไม่ต้องคุณลักษณะนี้ใครจะมีทั้งนำหน้าแต่ละบรรทัด//หรือเริ่มต้นส่วนที่มีและจบส่วนที่มี/* */ปัญหาของเทคนิคหลังคือความคิดเห็นไม่ซ้อนกันดังนั้นนักพัฒนาต้องตรวจสอบและจัดการใด ๆ*/ระหว่างจุดเริ่มต้นและจุดสิ้นสุด
Thomas Matthews

คำตอบ:


141

ไม่เพียง แต่ไม่ได้รับการดำเนินการ แต่ยังไม่ได้รวบรวม

#ifเป็นคำสั่งพรีโปรเซสเซอร์ซึ่งได้รับการประเมินก่อนขั้นตอนการคอมไพล์จริง รหัสภายในบล็อกนั้นจะไม่ปรากฏในไบนารีที่คอมไพล์

มักใช้เพื่อลบส่วนของโค้ดชั่วคราวโดยมีจุดประสงค์เพื่อเปิดใช้งานในภายหลัง


1
นี่เป็นความคิดเห็นจริงทุกประเภท ความแตกต่างที่สำคัญคือการทำรัง
Samy Bencherif

73

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

foo();
bar(x, y); /* x must not be NULL */
baz();

หากฉันต้องการแสดงความคิดเห็นฉันอาจลอง:

/*
foo();
bar(x, y); /* x must not be NULL */
baz();
*/

Bzzt ข้อผิดพลาดทางไวยากรณ์! ทำไม? เนื่องจากบล็อกความคิดเห็นไม่ซ้อนกันดังนั้น (ดังที่คุณเห็นจากการเน้นไวยากรณ์ของ SO) */หลังจากคำว่า "NULL" จะยุติความคิดเห็นทำให้การbazโทรไม่แสดงความคิดเห็นและข้อผิดพลาด*/หลังbazไวยากรณ์ ในทางกลับกัน:

#if 0
foo();
bar(x, y); /* x must not be NULL */
baz();
#endif

ทำงานเพื่อแสดงความคิดเห็นทั้งหมด และ#if 0s จะทำรังซึ่งกันและกันดังนี้:

#if 0
pre_foo();
#if 0
foo();
bar(x, y); /* x must not be NULL */
baz();
#endif
quux();
#endif

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


5
โปรดทราบว่ารหัสภายใน #if จะต้องถูกต้องตามศัพท์ (ตรงข้ามกับความคิดเห็น) และคำสั่งของตัวประมวลผลล่วงหน้ายังคงมีผลบังคับใช้ (ditto)
jpalecek

@ เดวิด: มันไม่ถูกต้องตามศัพท์ แต่มันจะยังคงรวบรวม ดังนั้นรหัสจึงไม่จำเป็นต้องถูกต้องตามศัพท์
Dennis Zickefoose

1
@ เดนนิสได้foo.c:3: unterminated string or character constantมาจาก gcc ใช้อะไรครับ?
David X

18

มันแสดงความคิดเห็นอย่างถาวรกับโค้ดนั้นดังนั้นคอมไพเลอร์จะไม่คอมไพล์

โค้ดเดอร์สามารถเปลี่ยน #ifdef เพื่อให้โค้ดนั้นคอมไพล์ในโปรแกรมได้ในภายหลังหากต้องการ

มันเหมือนกับว่าไม่มีรหัส


15

บล็อก #if 0 … #endif ทำหน้าที่อะไร

มันบอกคุณว่าผู้เขียนไม่เคยได้ยินเกี่ยวกับระบบควบคุมเวอร์ชัน ซึ่งจะบอกให้คุณวิ่งให้ไกลที่สุด ...



7

เมื่อตัวประมวลผลล่วงหน้าเห็น # หากตรวจสอบว่าโทเค็นถัดไปมีค่าที่ไม่ใช่ศูนย์หรือไม่ ถ้าเป็นเช่นนั้นจะคงรหัสไว้สำหรับคอมไพเลอร์ หากไม่เป็นเช่นนั้นระบบจะกำจัดรหัสนั้นออกเพื่อให้คอมไพเลอร์ไม่เห็น

หากมีคนพูดว่า #if 0 พวกเขากำลังแสดงความคิดเห็นเกี่ยวกับโค้ดอย่างมีประสิทธิภาพดังนั้นจะไม่มีการคอมไพล์ คุณสามารถคิดว่าสิ่งนี้เหมือนกับว่าพวกเขาใส่ / * ... * / รอบ ๆ มัน มันไม่เหมือนกัน แต่ก็มีผลเหมือนกัน

หากคุณต้องการทำความเข้าใจกับสิ่งที่เกิดขึ้นโดยละเอียดคุณสามารถดูได้ คอมไพเลอร์จำนวนมากจะอนุญาตให้คุณเห็นไฟล์หลังจากที่ตัวประมวลผลล่วงหน้าทำงานแล้ว ตัวอย่างเช่นบน Visual C ++ คำสั่ง switch / P จะเรียกใช้ตัวประมวลผลล่วงหน้าและใส่ผลลัพธ์ในไฟล์. i


ไม่มาก ตัวประมวลผลล่วงหน้าจะแยกวิเคราะห์ตามบรรทัดแทนที่จะแยกโดยโทเค็น ตามคำอธิบายของคุณมันเป็นไปไม่ได้ที่จะพูดเช่น#if WIN32 || __CYGWIN__แต่มันได้ผลตามที่คาดไว้
Ben Voigt

ฉันกำลังทำให้ง่ายขึ้น หากมีหรือจะตรวจสอบว่าโทเค็นไม่เป็นศูนย์หรือไม่ ในทำนองเดียวกันหากมีและจะตรวจสอบว่าทั้งสองไม่ใช่ศูนย์หรือไม่
Steve Rowe

3

เส้นที่เริ่มต้นด้วยการ#มีคำสั่ง preprocessor #if 0 [...] #endifบล็อกไม่ส่งไปยังคอมไพเลอร์และจะไม่สร้างรหัสเครื่อง

คุณสามารถสาธิตสิ่งที่เกิดขึ้นกับตัวประมวลผลล่วงหน้าด้วยไฟล์ต้นฉบับifdef.cxx:

#if 0
This code will not be compiled
#else
int i = 0;
#endif

การรันgcc -E ifdef.cxxจะแสดงสิ่งที่รวบรวม

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

นอกจากนี้คำตอบอาจเหมือนกันสำหรับทั้งCและC ++แต่ไม่มีภาษาที่เรียกว่า C / C ++ และไม่ใช่นิสัยที่ดีที่จะอ้างถึงภาษาดังกล่าว


4
เกิดอะไรขึ้นกับการพูดว่า C / C ++ เป็นชวเลขสำหรับ "C หรือ C ++" คุณคิดอย่างตรงไปตรงมาว่าใคร ๆ จะสับสนคิดว่ามีภาษาที่เรียกว่า "C / C ++" หรือไม่?
Christopher Barber

1
@ คริส: ผู้คนมักถามคำถามเช่น "ฉันจะ X ใน C / C ++ ได้อย่างไร" ซึ่งเป็นคำถามไร้สาระ; คุณกำลังเข้ารหัสอย่างใดอย่างหนึ่งและหากคุณยังไม่ได้เลือกคุณควรระบุอย่างชัดเจนในข้อเท็จจริงนั้น ใช่คนสับสนว่ามีภาษาที่เรียกว่า "C / C ++"
Dennis Zickefoose

1
ช่างเป็นคำพูดที่ไร้สาระ! มีคำถามมากมายที่มีคำตอบที่เกี่ยวข้องกับทั้ง C และ C ++ โปรดจำไว้ว่านี่เป็นเว็บไซต์สำหรับถามคำถาม เพียงเพราะคุณถามคำถามทั่วไปไม่ได้หมายความว่าคุณไม่รู้ว่าคุณใช้ภาษาอะไร หากคุณสงสัยว่าเป็นเช่นนั้นในคำถามนี้จะช่วยระบุ C หรือ C ++ ได้อย่างไร คุณคิดว่าจะมีประโยชน์หรือไม่หากทุกคำถามที่สามารถใช้ได้กับ C หรือ C ++ ถูกถามสองครั้ง
Christopher Barber

@ คริสโตเฟอร์: คุณพูดถูกมีคำถามมากมายที่คำตอบเกี่ยวข้องกับ C, C ++ และ Objective-C (นี่เป็นหนึ่งในนั้น) Stack Overflow มีระบบการติดแท็กที่สะดวกเพื่อระบุว่าคำถามเป็นของภาษาใด ดังที่ @Dennis กล่าวถึง SO (และฟอรัมการเขียนโปรแกรมอื่น ๆ [fora?]) มีหลายคน (เช่นกัน) ที่สับสนเกี่ยวกับการแยกระหว่างภาษา C และภาษาที่ได้รับ C อื่น ๆ ซึ่งอ้างถึงภาษาเหล่านี้แทนกันได้ว่า C / C ++ ทำให้ ยากที่จะตอบคำถามด้วยภาษาที่เหมาะสม
Johnsyweb

2

ไม่มาก

int main(void)
{
   #if 0
     the apostrophe ' causes a warning
   #endif
   return 0;
}

มันแสดง "tc: 4: 19: warning: ไม่มีการยุติ" character "ด้วย gcc 4.2.4


2
คำเตือนนี้สร้างขึ้นโดยตัวประมวลผลล่วงหน้าไม่ใช่คอมไพเลอร์ คอมไพเลอร์เท่านั้นที่จะเห็น: # 1 "tc" # 1 "<built-in>" # 1 "<command-line>" # 1 "tc" int main (void) {return 0; }
Johnsyweb

0

เป็นวิธีที่ถูกในการแสดงความคิดเห็น แต่ฉันสงสัยว่าอาจมีโอกาสในการดีบัก ตัวอย่างเช่นสมมติว่าคุณมีบิลด์ที่ส่งออกค่าไปยังไฟล์ คุณอาจไม่ต้องการสิ่งนั้นในเวอร์ชันสุดท้ายเพื่อให้คุณสามารถใช้ #if 0 ... #endif

นอกจากนี้ฉันสงสัยว่าวิธีที่ดีกว่าในการทำเพื่อจุดประสงค์ในการดีบักคือทำ:

#ifdef DEBUG
// output to file
#endif

คุณสามารถทำอะไรแบบนั้นได้และมันอาจจะเข้าท่ากว่าและสิ่งที่คุณต้องทำคือกำหนด DEBUG เพื่อดูผลลัพธ์

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