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

Barbara Streisand
Lepaskan: 2024-11-16 02:17:03
asal
236 orang telah melayarinya

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
Salin selepas log masuk

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)
Salin selepas log masuk

Menilai A(blah) menghasilkan output berikut:

blah B (blah)
Salin selepas log masuk

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)
Salin selepas log masuk

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__)))
Salin selepas log masuk

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(...)
Salin selepas log masuk

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)
Salin selepas log masuk

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__)
Salin selepas log masuk

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))
Salin selepas log masuk

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!

sumber:php.cn
Kenyataan Laman Web ini
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
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan