Pragma ในกำหนดมาโคร


100

มีวิธีบางอย่างในการฝังคำสั่ง pragma ในมาโครด้วยคำสั่งอื่น ๆ หรือไม่?

ฉันพยายามที่จะบรรลุสิ่งที่ต้องการ:

#define DEFINE_DELETE_OBJECT(type)                      \
    void delete_ ## type_(int handle);                  \
    void delete_ ## type(int handle);                                                \
    #pragma weak delete_ ## type_ = delete_ ## type

ฉันโอเคกับโซลูชันการเพิ่มประสิทธิภาพ (บันทึกสำหรับคลื่น) ถ้ามีอยู่


5
อาจจะไม่ใช่ - #pragmas ไม่ได้กำหนดโดยมาตรฐาน C หรือ C ++

ตัวประมวลผลก่อนคือแม้ว่าคำสั่งย่อยที่อนุญาตเฉพาะที่เขาต้องการเรียกใช้จะไม่ใช่ก็ตาม
Puppy

@DeadMG: มีหลายสิ่งหลายอย่างที่พบบ่อยระหว่าง C และ C ++ แม้ว่าการประมวลผลล่วงหน้าส่วนใหญ่จะเป็นเรื่องธรรมดา แต่ก็มีความแตกต่างที่สำคัญในการระบุวิธีการประมวลผลล่วงหน้าขึ้นอยู่กับมาตรฐานภาษาที่ใช้ (C89, C99, C ++ และ C ++ 0x FCD)
James McNellis

2
@ James McNellis: เนื่องจากในทางเทคนิคแล้วโปรแกรม C ส่วนใหญ่สามารถพกพาไปยัง C ++ ไม่ได้ทำให้ฟังก์ชันการทำงานทั่วไปอย่างแท้จริงเนื่องจากไม่มีโปรแกรมเมอร์ C ++ ที่ทำส่วนใหญ่ได้ ทั้งสองภาษาไม่มีอะไรเหมือนกันมากนัก
Puppy

คำตอบ:


116

หากคุณใช้ c99 หรือ c ++ 0x จะมีตัวดำเนินการ pragma ซึ่งใช้เป็น

_Pragma("argument")

ซึ่งเทียบเท่ากับ

#pragma argument

ยกเว้นว่าสามารถใช้ในมาโครได้ (ดูหัวข้อ 6.10.9 ของมาตรฐาน c99 หรือ 16.9 ของร่างคณะกรรมการขั้นสุดท้าย c ++ 0x)

ตัวอย่างเช่น,

#define STRINGIFY(a) #a
#define DEFINE_DELETE_OBJECT(type)                      \
    void delete_ ## type ## _(int handle);                  \
    void delete_ ## type(int handle);                   \
    _Pragma( STRINGIFY( weak delete_ ## type ## _ = delete_ ## type) )
DEFINE_DELETE_OBJECT(foo);

เมื่อใส่เข้าไปgcc -Eให้

void delete_foo_(int handle); void delete_foo(int handle);
#pragma weak delete_foo_ = delete_foo
 ;

32
ในฐานะ FYI: MSVC มี__pragma()ตัวดำเนินการตัวประมวลผลก่อนซึ่งน่าเสียดายที่แตกต่างจาก_Pragma()ตัวดำเนินการของ C99 เล็กน้อย(C99 ใช้สตริงลิเทอรัล MSVC ใช้โทเค็นที่ไม่ได้อยู่ในสตริง): msdn.microsoft.com/en-us/library/d9x1s805 .aspx
Michael Burr

15
@MichaelBurr MSVC จะต้องแตกต่างเสมอใช่หรือไม่?
โธมัส

5

สิ่งที่ดีอย่างหนึ่งที่คุณสามารถทำได้กับ _Pragma ("อาร์กิวเมนต์") คือใช้เพื่อจัดการกับปัญหาบางอย่างของคอมไพเลอร์เช่น

#ifdef _MSC_VER
#define DUMMY_PRAGMA _Pragma("argument")
#else
#define DUMMY_PRAGMA _Pragma("alt argument")
#endif

0

ไม่ไม่มีวิธีพกพาในการทำเช่นนั้น จากนั้นอีกครั้งไม่มีวิธีพกพาในการใช้ #pragma เลย ด้วยเหตุนี้คอมไพเลอร์ C / C ++ จำนวนมากจึงกำหนดวิธีการของตนเองในการทำสิ่งที่เหมือนปราม่าและมักจะฝังอยู่ในมาโครได้ แต่คุณต้องมีนิยามมาโครที่แตกต่างกันในทุกคอมไพเลอร์ หากคุณยินดีที่จะไปเส้นทางนั้นคุณมักจะทำสิ่งนี้:

#if defined(COMPILER_GCC)
#define Weak_b
#define Weak_e __attribute__((weak))
#elif defined(COMPILER_FOO)
#define Weak_b __Is_Weak
#define Weak_e
#endif

#define DEFINE_DELETE_OBJECT(type)                      \
    Weak_b void delete_ ## type_(int handle) Weak_e;    \
    Weak_b void delete_ ## type(int handle)  Weak_e;    

ในกรณีที่ไม่ชัดเจนคุณต้องการกำหนดWeak_bและWeak_eเป็นโครงสร้างการถ่ายคร่อมเริ่มต้นและสิ้นสุดเนื่องจากคอมไพเลอร์บางตัวเช่น GCC เพิ่มแอตทริบิวต์เป็นส่วนเสริมในลายเซ็นประเภทและบางส่วนเช่น MSC เพิ่มเป็นคำนำหน้า (หรืออย่างน้อยก็ทำ ครั้งหนึ่งเป็นเวลาหลายปีแล้วที่ฉันใช้ MSC) การมีโครงร่างคร่อมช่วยให้คุณสามารถกำหนดสิ่งที่ใช้ได้ผลเสมอแม้ว่าคุณจะต้องส่งลายเซ็นประเภททั้งหมดไปยังโครงสร้างคอมไพเลอร์

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

โอ้ฉันสงสัยว่าคุณต้องกำหนด Weak_b และ Weak_e เป็นมาโครที่ใช้พารามิเตอร์ แต่ฉันไม่เต็มใจที่จะอ่านเอกสารเกี่ยวกับวิธีสร้างคำจำกัดความที่อ่อนแอสำหรับตัวอย่างนี้ ฉันฝากไว้เป็นแบบฝึกหัดสำหรับผู้อ่าน


-3

มีวิธีบางอย่างในการฝังคำสั่ง pragma ในมาโครด้วยคำสั่งอื่น ๆ หรือไม่?

ไม่คุณไม่สามารถใส่คำสั่งของตัวประมวลผลล่วงหน้าลงในคำสั่งของตัวประมวลผลล่วงหน้าได้ อย่างไรก็ตามคุณสามารถใส่ลงในinlineฟังก์ชันได้ ที่เอาชนะCแท็กแม้ว่า


1
สิ่งที่ดีที่จะนำไปใช้ในฟังก์ชันอินไลน์ทำได้ คำสั่งตัวประมวลผลล่วงหน้าจะถูกประมวลผลก่อนสิ่งใดก็ตามที่สามารถจดจำฟังก์ชันได้

2
C99 มี inlineและการใช้งาน C89 ที่สำคัญส่วนใหญ่มีการเปลี่ยนแปลงบางอย่าง
Chris Lutz

@ คริสสมมติว่าความคิดเห็นของคุณถูกส่งมาที่ฉัน - ประเด็นของคุณคืออะไร?

@ นีล - ไม่ขอโทษ ฉันกำกับไว้ที่ประโยคสุดท้ายของ @ sbi
Chris Lutz

1
@ คริส: อ๊ะ ๆ ๆ inlineยังเป็นอีกสิ่งที่ C ยืมมาจาก C ++! :)
sbi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.