ผลลัพธ์ของรหัส 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
ที่จะได้รับคุณควรเขียน729
CUBE((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+5
49
กำหนดมาโครตามที่#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