ผลลัพธ์ของรหัส C นี้คือ 49 แต่ใครสามารถอธิบายฉันได้บ้าง [ซ้ำ]
#include <stdio.h>
#define CUBE(x) (x * x * x)
int main() {
printf("%d", CUBE(4+5));
return 0;
}
คำตอบ
มาโครจะเปลี่ยนรหัสเป็น:
printf("%d", (4+5 * 4+5 * 4+5));
ซึ่งมีประสิทธิภาพ:
printf("%d", 4 + (5*4) + (5*4) + 5); // 29
หากคุณต้องการก้อน9ที่จะได้รับคุณควรเขียน729CUBE((4+5))
นี่คือวิธีขยายมาโครในระหว่างกระบวนการคอมไพล์:
printf("%d", (4+5 * 4+5 * 4+5));
เนื่องจาก*มีลำดับความสำคัญสูงกว่า+นิพจน์นี้จึงถูกประเมินว่า(4 + (5 * 4) + (5 * 4) + 5)สร้างขึ้น49แทนที่จะเป็นที่คาด729ไว้
เพื่อหลีกเลี่ยงปัญหาลำดับความสำคัญของตัวดำเนินการดังกล่าวอาร์กิวเมนต์แมโครทั้งหมดจะต้องอยู่ในวงเล็บในนิยามมาโครเช่นเดียวกับนิพจน์เอง:
#define CUBE(x) ((x) * (x) * (x))
อย่างไรก็ตามโปรดทราบว่าการขยายตัวของการCUBEประเมินxหลายครั้งซึ่งเป็นปัญหาหากอาร์กิวเมนต์มาโครมีผลข้างเคียงเช่นCUBE(i++).
เพื่อหลีกเลี่ยงปัญหาเหล่านี้ทั้งหมดให้ใช้ฟังก์ชันและปล่อยให้คอมไพเลอร์ปรับให้เหมาะสม:
int cube(int x) {
return x * x * x;
}
คุณสามารถเพิ่มstatic inlineหน้านิยามฟังก์ชันนี้ได้ แต่เครื่องมือเพิ่มประสิทธิภาพสมัยใหม่จะยังคงแทรกฟังก์ชันไว้โดยไม่มีสิ่งนี้
ตัวประมวลผลก่อนหน้า C จะแทนที่อินสแตนซ์ทั้งหมดของ x เป็น 4 + 5 ตามตัวอักษรซึ่งส่งผลให้เกิดรหัสต่อไปนี้:
i = 4+5*4+5*4+5;
(การคูณก่อนแล้วจึงบวก)
คุณจะต้องให้การป้อนข้อมูลเช่นถ้าคุณต้องการที่จะเพิ่มตัวเลขแล้วส่งไปที่CUBE((4+5)) CUBEสาเหตุ TH CUBE(4+5)มีการขยายพื้นเพื่อ4+5*4+5*4+5เป็นมันชุดทั้งในสถานที่ของ4+5 xดังนั้น4+5*4+5*4+5= คูณมาก่อนแล้วเพิ่มพวกเขาจะให้4+20+20+549
กำหนดมาโครตามที่#define CUBE(x) ((x)*(x)*(x))เป็นจริงขั้นแรกให้(4+5)ดำเนินการสำหรับทุก ๆ ครั้ง(x)แล้วจึงทำการ*ดำเนินการ
อีกวิธีหนึ่งคือใช้CUBE((4+5))ในขณะที่เรียกมาโครโดยพื้นฐานแล้วจะเพิ่มตัวเลขสองตัวและ(4+5)= 9แล้วทำCUBE(9)เช่น:
#include<stdio.h>
#define CUBE(x) (x * x * x)
int main( )
{
printf("%d", CUBE((4+5)));
return 0;
}
อ่านสมัยใหม่ Cแล้วn1570 C ร่างมาตรฐานและเอกสารของGCCและGDBและCPP ดูเว็บไซต์อ้างอิง C นี้ด้วย
รับแรงบันดาลใจจากที่มีอยู่โครงการโอเพนซอร์สเช่นบนGitHubหรือซอฟแวร์ GNU
ด้วยคอมไพเลอร์GCCล่าสุดให้เรียกใช้เป็นgcc -Wall -Wextra -gไฟล์. ใช้-C -Eตัวเลือกเพื่อรับแบบฟอร์มที่ประมวลผลล่วงหน้า
คุณอาจสนใจโดยส่วนขยายstatement-exprของ GCC
คุณCUBE(4+5)จะมหภาคขยายไป4+5*4+5*4+5ซึ่งจะคำนวณ4+(5*4)+(5*4)+5ตามแบบอย่างของผู้ประกอบการ C
พิจารณาการเข้ารหัสstatic inlineฟังก์ชันเช่น
static inline int cube(int x) { return x*x*x; }
หรือถ้าคุณต้องการมาโครอย่างน้อย
#define CUBE(X) ((X)*(X)*(X))
ซึ่งจะใช้งานได้ไม่ดีนักCUBE(i++)(ในขณะที่ใช้inlineฟังก์ชั่นcube(i++)ทำในสิ่งที่คุณต้องการให้ทำ: เพิ่มiครั้งเดียว!)
BTW คุณสามารถใช้GPPหรือGNU m4 (หรือเครื่องกำเนิดไฟฟ้าของคุณเองหรือGNU bison ) เพื่อสร้างรหัส C ตามหลักทั่วไปให้คิดด้วยAST s: เมื่อคุณสร้างรหัส C จะปล่อยวงเล็บที่ไร้ประโยชน์มากมายเช่นในChicken Scheme , SWIGหรือในCAIAหรือในmanydl.cของฉัน
คุณยังสามารถใช้Clang static analyzerกับโค้ดของคุณได้ (และอาจจะเป็นFrama-C )
คุณอาจจะสนใจในการอ่านแนวทางการเข้ารหัสบางอย่างเช่นMISRA Cหรือคน GNU