int main()
{
i/*nt*/a = 10;
return 0;
}
หากฉันมีรหัสด้านบนและต้องการนับโทเค็นจะเป็นโทเค็น 14 หรือ 13 หรือไม่?
การเขียนความคิดเห็นภายในชื่อตัวแปรถูกต้องหรือไม่ คุณสามารถคิดว่าint i
, int a
, int ia
มีการกำหนดทั่วโลก
int main()
{
i/*nt*/a = 10;
return 0;
}
หากฉันมีรหัสด้านบนและต้องการนับโทเค็นจะเป็นโทเค็น 14 หรือ 13 หรือไม่?
การเขียนความคิดเห็นภายในชื่อตัวแปรถูกต้องหรือไม่ คุณสามารถคิดว่าint i
, int a
, int ia
มีการกำหนดทั่วโลก
คำตอบ:
ความคิดเห็นจะถูกลบออกในช่วงที่ 3 ของการแปลโปรแกรม1 : แต่ละความคิดเห็นจะถูกแทนที่ด้วยอักขระเว้นวรรคหนึ่งตัว ดังนั้นความคิดเห็น/*nt*/
จึงไม่ใช่โทเค็นอย่างแน่นอน
ถ้าไม่มีint
, main
, i
, a
หรือreturn
จะถูกกำหนดเป็น preprocessing แมโครแยกโปรแกรมผลิต14ราชสกุล (ไม่ใช่ 13):
int
main
(
)
{
i
a
=
10
;
return
0
;
}
เว้นแต่i
จะกำหนดเป็นประเภทที่มีtypedef
คำสั่งจะมีข้อผิดพลาดทางไวยากรณ์เป็นi a
ไม่ตรงกับกฎในไวยากรณ์ C
ดังนั้นคุณจึงไม่สามารถเขียนความคิดเห็นภายในชื่อตัวแปรได้ความคิดเห็นจะแบ่งตัวระบุออกเป็น 2 โทเค็นแยกกัน นี่เป็นจริงสำหรับโทเค็นการประมวลผลล่วงหน้าและภาษา C 2 2
อย่างไรก็ตามโปรดทราบว่าคุณสามารถแทรกข้อคิดเห็นในตำแหน่งที่ผิดปกติเช่นระหว่างตัวดำเนินการยูนารีกับตัวถูกดำเนินการหรือระหว่าง#
คำสั่งและการประมวลผลล่วงหน้าและอาร์กิวเมนต์:
/**/#/**/include/**/<stdio.h>/**///////////////////////
/**/#/**/define/**/STAT/**/(/**/a/**/)/**/-/**/1/**////
/**/#/**/ifdef/**/STAT/**//////////////////////////////
/**/int/**/main/**/(/**/)/**/{/**//////////////////////
/**/int/**/a/**/=/**/+/**/1/**/;/**////////////////////
/**/printf/**/(/**/"Hello "/**/"world!\n"/**/)/**/;/**/
/**/return/**/STAT/**/;/**/////////////////////////////
/**/}/**///////////////////////////////////////////////
/**/#/**/endif/**//////////////////////////////////////
แต่นิยามมาโครข้างต้นไม่ได้กำหนดมาโครที่เหมือนฟังก์ชัน แต่เป็นมาโครปกติSTAT
ที่ขยายเป็น( a ) - 1
ที่ขยายเพื่อ
ชื่อตัวแปรเช่นเดียวกับโทเค็นอื่น ๆ สามารถแบ่งโดยขึ้นบรรทัดใหม่ที่ใช้ Escape บรรทัดใหม่ที่หลีกเลี่ยงคือลำดับหรือ\
ตามด้วยขึ้นบรรทัดใหม่ทันที ลำดับเหล่านี้จะถูกลบออกจากซอร์สโค้ดระหว่างขั้นตอนที่ 2 ของการแปลโปรแกรม จุดประสงค์หลักของพวกเขาคือการทำลายนิยามมาโครแบบยาวในหลายบรรทัด
ด้านล่างนี้คือโค้ดแฟรกเมนต์3ที่สร้างโทเค็น 14 แบบเดียวกัน:
\
i\
nt\
ma\
in()
{\
i/\
*nt\
*/a \
= 10;
r\
et\
urn\
0;}
สังเกตว่า code colorizer พลาดคำหลักที่หั่นและหั่นสี่เหลี่ยมลูกเต๋าและแสดงความคิดเห็นได้อย่างไร :)
1) พฤติกรรมนี้ระบุไว้ใน ANSI-C aka C89 คอมไพเลอร์โบราณบางตัวมีพฤติกรรมที่แตกต่างกันเล็กน้อยซึ่งส่งผลให้มีการวางโทเค็น แต่ลักษณะเฉพาะดังกล่าวเป็นที่สนใจในประวัติศาสตร์เท่านั้น
2) คุณสามารถแทรกข้อคิดเห็นภายในค่าคงที่ของสตริงได้โดยใช้ประโยชน์จากความจริงที่ว่าค่าคงที่ของสตริงที่อยู่ติดกันจะเชื่อมต่อกันในขั้นตอนที่ 6 ของการแปลโปรแกรม: printf("Hello "/* my name is Luca */"world!\n");
3) รูปแบบการนำเสนอต้นคริสต์มาสนี้ไม่ได้มีไว้สำหรับใช้ในโปรแกรมจริง แต่จะแสดงให้เห็นถึงวิธีการใช้ความสามารถในการจัดการอินพุตของ C ในทางที่ผิด เทคนิคที่ซับซ้อนมากขึ้นได้รับรางวัลการประกวดรหัส C ที่ทำให้สับสนระหว่างประเทศ
\r
ก่อนหน้าไฟล์\n
. ยังมีกรณีที่สิ่งนี้จะย้อนกลับ: ความคิดเห็นอาจมี \ ตัวอักษรตามด้วยช่องว่างโดยเฉพาะเพื่อหลีกเลี่ยงการวางบรรทัด:const char *path = "C:\\"; // the default path is C:\
The path is "C:\"
นี้ดูเหมือนจะดีกว่าการให้ความหมายของรหัสขึ้นอยู่กับการขึ้นบรรทัดใหม่
จากมุมมองของคำศัพท์ความคิดเห็นจะเหมือนกับการเว้นวรรค
มาตรา 6.4p3 ของมาตรฐาน Cเกี่ยวกับสถานะของคำศัพท์:
... ราชสกุลกระบวนการเตรียมการผลิตสามารถแยกออกจากพื้นที่สีขาว ; ซึ่งประกอบด้วยข้อคิดเห็น (อธิบายในภายหลัง) หรืออักขระเว้นวรรค (ช่องว่างแท็บแนวนอนบรรทัดใหม่แท็บแนวตั้งและฟีดแบบฟอร์ม) หรือทั้งสองอย่าง ...
โดยเฉพาะอย่างยิ่งความคิดเห็นจะถูกแปลเป็นช่องว่างเดียว สิ่งนี้ระบุไว้ในส่วน 5.1.1.2p3:
ไฟล์ต้นฉบับถูกย่อยสลายเป็นโทเค็นก่อนการประมวลผลและลำดับของอักขระเว้นวรรค (รวมถึงความคิดเห็น) ไฟล์ต้นฉบับจะต้องไม่จบลงด้วยโทเค็นการประมวลผลล่วงหน้าบางส่วนหรือในข้อคิดเห็นบางส่วน แต่ละความคิดเห็นจะถูกแทนที่ด้วยอักขระเว้นวรรคหนึ่งตัว อักขระบรรทัดใหม่จะยังคงอยู่ ลำดับอักขระช่องว่างที่ไม่ว่างแต่ละลำดับนอกเหนือจากบรรทัดใหม่จะยังคงอยู่หรือถูกแทนที่ด้วยอักขระช่องว่างหนึ่งอักขระที่กำหนดโดยการนำไปใช้งาน
เพื่อแสดงให้เห็นถึงสิ่งนี้หากคุณส่งรหัสของคุณผ่านตัวประมวลผลล่วงหน้าคุณจะได้รับ:
int main()
{
i a = 10;
return 0;
}
ดังนั้นความคิดเห็นเช่นช่องว่างทำหน้าที่แยกโทเค็น
ซึ่งหมายความว่ารหัสจะมี 14 โทเค็นไม่ใช่ 13
ผลลัพธ์จะเป็นเหมือนที่คุณเขียนไว้:
i a = 10;
ไม่:
ia = 10;
เพียงตรวจสอบว่าโค้ดของคุณอยู่ในรูปแบบใด
int main()
{
int i/*nt*/a = 10;
return 0;
}
จะมีหลังจากการประมวลผลล่วงหน้า เพียงเพิ่มแฟล็ก "-E" ในคอมไพเลอร์ของคุณ gcc -E myscript.c และคุณจะได้ผลลัพธ์:
e.sharaborin@landau:~$ gcc -E myscript.c
# 1 "myscript.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "myscript.c"
int main()
{
int i a = 10;
return 0;
}
และแน่นอนคุณสามารถสรุปได้ว่ามีข้อผิดพลาด
ใช่คุณสามารถทำได้ ความคิดเห็นจะถูกข้ามโดยคอมไพเลอร์ พวกเขาจะไม่ส่งผลกระทบต่อตัวแปร มันจะเหมือนกันอย่าลืมปิดแท็กความคิดเห็น
i a
หรือia
?
cpp -traditional
ia = 10;
ก็จะขยายตัวออกไป