Rumah >pembangunan bahagian belakang >C++ >Bagaimanakah anda boleh mencapai fungsi makro rekursif dalam C, walaupun terdapat had pengembangan makro?

Bagaimanakah anda boleh mencapai fungsi makro rekursif dalam C, walaupun terdapat had pengembangan makro?

Barbara Streisand
Barbara Streisandasal
2024-11-16 02:17:03324semak imbas

How can you achieve recursive macro functionality in C, despite the limitations of macro expansion?

Makro Rekursif dalam C Menggunakan Makro Argumen

Dalam pengaturcaraan C, tidak mudah untuk menggunakan makro secara rekursif pada hujah makro. Walau bagaimanapun, menggunakan penyelesaian yang kompleks, adalah mungkin untuk mencapai makro MAP dengan fungsi yang diingini.

Prinsip Teras

Untuk memulakan rekursi, kami mentakrifkan makro MAP_OUT yang berfungsi sebagai pemegang tempat untuk pengembangan makro:

#define MAP_OUT

Seterusnya, kami mencipta dua makro, A dan B, untuk menunjukkan rekursi:

#define A(x) x B MAP_OUT (x)
#define B(x) x A MAP_OUT (x)

Menilai A(blah) menghasilkan output berikut:

blah B (blah)

Prapemproses menganggap B(blah) sebagai teks biasa kerana ia belum lagi panggilan makro. Apabila teks ini diproses semula, ia mengembang untuk menghasilkan:

blah blah A (blah)

Dengan terus menyuap keluaran semula ke dalam prapemproses, kami boleh mengekalkan rekursi selama-lamanya.

Penilaian Rekursif

Untuk mengautomasikan penilaian berulang ini, kami menggunakan EVAL makro:

#define EVAL0(...) __VA_ARGS__
#define EVAL1(...) EVAL0 (EVAL0 (EVAL0 (__VA_ARGS__)))
#define EVAL2(...) EVAL1 (EVAL1 (EVAL1 (__VA_ARGS__)))
#define EVAL3(...) EVAL2 (EVAL2 (EVAL2 (__VA_ARGS__)))
#define EVAL4(...) EVAL3 (EVAL3 (EVAL3 (__VA_ARGS__)))
#define EVAL(...)  EVAL4 (EVAL4 (EVAL4 (__VA_ARGS__)))

Makro EVAL menyebarkan hujahnya melalui pepohon panggilan makro, mendarabkan kiraan penilaiannya sebanyak 365.

Penamatan Rekursi

Untuk mengelakkan pengulangan yang tidak berkesudahan, kita memerlukan mekanisme untuk penamatan. Kami mentakrifkan makro khas bernama MAP_END:

#define MAP_END(...)

Apabila dinilai, makro ini tidak melakukan apa-apa, menghentikan rekursi dengan berkesan.

Untuk memilih antara makro rekursif dan penamatan, kami memperkenalkan MAP_NEXT:

#define MAP_NEXT0(item, next, ...) next MAP_OUT
#define MAP_NEXT1(item, next) MAP_NEXT0 (item, next, 0)
#define MAP_NEXT(item, next)  MAP_NEXT1 (MAP_GET_END item, next)

MAP_NEXT membandingkan item semasa dengan penanda senarai akhir (). Ia mengembalikan MAP_END jika ia sepadan, atau parameter seterusnya sebaliknya.

Pelaksanaan Praktikal

Menggabungkan elemen ini, kami boleh mencipta versi praktikal makro A dan B:

#define MAP0(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP1) (f, peek, __VA_ARGS__)
#define MAP1(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP0) (f, peek, __VA_ARGS__)

MAP0 dan MAP1 menggunakan operasi f pada item semasa x. Mereka kemudian menyemak item seterusnya, mengintip, untuk menentukan sama ada untuk meneruskan atau menamatkan rekursi.

Akhir sekali, kami mengikat semuanya bersama-sama dengan makro MAP peringkat atas:

#define MAP(f, ...) EVAL (MAP1 (f, __VA_ARGS__, (), 0))

Tempat MAP penanda senarai akhir pada senarai argumen dan melepasinya melalui EVAL.

Dengan menggunakan teknik ini, anda boleh mencapai makro rekursif kefungsian dalam C, membolehkan pemprosesan berasaskan makro yang kompleks.

Atas ialah kandungan terperinci Bagaimanakah anda boleh mencapai fungsi makro rekursif dalam C, walaupun terdapat had pengembangan makro?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn