{"id":34518,"date":"2025-11-18T04:31:38","date_gmt":"2025-11-18T01:31:38","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/"},"modified":"2025-11-18T04:31:38","modified_gmt":"2025-11-18T01:31:38","slug":"c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/","title":{"rendered":"C23 \u00d6ncesi `__VA_OPT__` Alternatifi: Geli\u015fmi\u015f C Makrolar\u0131"},"content":{"rendered":"<p><body><\/p>\n<p>C ve C++ programlamas\u0131nda, esnek ve yeniden kullan\u0131labilir kod bloklar\u0131 olu\u015fturmak i\u00e7in \u00f6ni\u015flemci makrolar\u0131 vazge\u00e7ilmez ara\u00e7lard\u0131r. Ancak, de\u011fi\u015fken say\u0131da arg\u00fcman alan (variadic) makrolarla \u00e7al\u0131\u015f\u0131rken, \u00f6zellikle bu arg\u00fcmanlar\u0131n iste\u011fe ba\u011fl\u0131 oldu\u011fu durumlarda, klasik yakla\u015f\u0131mlar belirli zorluklar \u00e7\u0131kar\u0131r. C23 ve C++20 standartlar\u0131 ile gelen <code class=\"language-c\">__VA_OPT__<\/code> makrosu bu sorunu zarif\u00e7e \u00e7\u00f6zse de, daha eski derleyiciler ve standartlarla \u00e7al\u0131\u015fmak zorunda kalan geli\u015ftiriciler i\u00e7in bu \u00f6zellik bir l\u00fckst\u00fcr. Peki, <code class=\"language-c\">__VA_OPT__<\/code> olmadan, iste\u011fe ba\u011fl\u0131 makro arg\u00fcmanlar\u0131n\u0131 temiz ve hatas\u0131z bir \u015fekilde nas\u0131l y\u00f6netebiliriz? Bu makale, tam da bu soruya odaklanarak, geli\u015fmi\u015f C \u00f6ni\u015flemci makrolar\u0131 kullanarak bu eksikli\u011fi gidermenin yollar\u0131n\u0131 ad\u0131m ad\u0131m a\u00e7\u0131klayacak ve ger\u00e7ek d\u00fcnya senaryolar\u0131yla destekleyecektir. Eski sistemlerde dahi modern esnekli\u011fi yakalamak isteyenler i\u00e7in kapsaml\u0131 bir rehber niteli\u011findedir.<\/p>\n<div class=\"tip\">\n        Uzman \u0130pucu: <code class=\"language-c\">__VA_OPT__<\/code>, bo\u015f olan <code class=\"language-c\">__VA_ARGS__<\/code> durumunda arg\u00fcmanlar\u0131n \u00f6n\u00fcne virg\u00fcl gelmesini veya arg\u00fcmanlar\u0131n hi\u00e7 geni\u015fletilmemesini sa\u011flayarak, <code class=\"language-c\">printf<\/code> benzeri fonksiyonel makrolar\u0131 \u00e7ok daha basit hale getirir. Bu makale boyunca bu esnekli\u011fi taklit etmenin yollar\u0131n\u0131 ke\u015ffedece\u011fiz.\n    <\/div>\n<h2>Variadic Makrolar ve <code class=\"language-c\">__VA_ARGS__<\/code> D\u00fcnyas\u0131na H\u0131zl\u0131 Bir Bak\u0131\u015f<\/h2>\n<p>C \u00f6ni\u015flemcisi, derleme \u00f6ncesinde kodda metinsel de\u011fi\u015fiklikler yapmam\u0131z\u0131 sa\u011flayan g\u00fc\u00e7l\u00fc bir ara\u00e7t\u0131r. Makrolar, kod tekrar\u0131n\u0131 azaltmak, platform ba\u011f\u0131ml\u0131l\u0131klar\u0131n\u0131 gidermek ve daha okunabilir soyutlamalar olu\u015fturmak i\u00e7in yayg\u0131n olarak kullan\u0131l\u0131r. \u00d6zellikle <code>printf<\/code> gibi fonksiyonlar\u0131n davran\u0131\u015f\u0131n\u0131 taklit eden, de\u011fi\u015fken say\u0131da arg\u00fcman alabilen makrolar, g\u00fcnl\u00fck programlama prati\u011fimizin \u00f6nemli bir par\u00e7as\u0131d\u0131r. Bu t\u00fcr makrolara &#8220;variadic makrolar&#8221; denir ve arg\u00fcman listesinin sonunda yer alan \u00fc\u00e7 nokta (<code>...<\/code>) ile tan\u0131mlan\u0131rlar. Bu de\u011fi\u015fken arg\u00fcmanlar, makro i\u00e7inde <code>__VA_ARGS__<\/code> \u00f6zel tan\u0131mlay\u0131c\u0131s\u0131 arac\u0131l\u0131\u011f\u0131yla eri\u015filebilir hale gelir.<\/p>\n<p>\u00d6rne\u011fin, basit bir hata ay\u0131klama mesaj\u0131 makrosu \u015fu \u015fekilde tan\u0131mlanabilir:<\/p>\n<div class=\"code-block\">\n<pre><code class=\"language-c\">\n#include <stdio.h>\n\n#define DEBUG_LOG(format, ...) \\\n    printf(\"DEBUG: \" format \"\\n\", __VA_ARGS__)\n\nint main() {\n    int x = 10;\n    DEBUG_LOG(\"x degeri: %d\", x); \/\/ \u00c7\u0131kt\u0131: DEBUG: x degeri: 10\n    DEBUG_LOG(\"Basit bir mesaj\"); \/\/ Derleme hatas\u0131 veya uyar\u0131!\n    return 0;\n}\n        <\/pre>\n<p><\/code>\n    <\/div>\n<p>Yukar\u0131daki \u00f6rnekte, <code class=\"language-c\">DEBUG_LOG(\"x degeri: %d\", x);<\/code> \u00e7a\u011fr\u0131s\u0131 bekledi\u011fimiz gibi \u00e7al\u0131\u015f\u0131r. Ancak, <code class=\"language-c\">DEBUG_LOG(\"Basit bir mesaj\");<\/code> \u00e7a\u011fr\u0131s\u0131 bir sorun yarat\u0131r. Neden mi? \u00c7\u00fcnk\u00fc <code class=\"language-c\">__VA_ARGS__<\/code> bo\u015f oldu\u011funda, makro geni\u015flemesi <code class=\"language-c\">printf(\"DEBUG: Basit bir mesaj\\n\", );<\/code> \u015feklinde olacakt\u0131r. Sondaki fazladan virg\u00fcl (<code class=\"language-c\">,<\/code>) derleyici hatas\u0131na veya en iyi ihtimalle bir uyar\u0131ya neden olur. \u0130\u015fte bu \"sondaki virg\u00fcl sorunu\", <code class=\"language-c\">__VA_OPT__<\/code>'un \u00e7\u00f6z\u00fcm sundu\u011fu temel problemdir.<\/p>\n<p>Bu problem, makrolar\u0131m\u0131z\u0131 esnek bir \u015fekilde tasarlamam\u0131z\u0131 engeller. Bazen makronun sadece bir format dizesi almas\u0131n\u0131 isteriz, bazen de bu format dizesiyle birlikte ek arg\u00fcmanlar almas\u0131n\u0131. Ancak <code class=\"language-c\">__VA_ARGS__<\/code> bo\u015fken bile her zaman bir virg\u00fcl b\u0131rakmas\u0131, bu ikili davran\u0131\u015f\u0131 standart C ve C++ \u00f6ni\u015flemcisi ile do\u011frudan sa\u011flamam\u0131z\u0131 zorla\u015ft\u0131r\u0131r. \u0130\u015fte bu noktada, <code class=\"language-c\">__VA_OPT__<\/code>'un sa\u011flad\u0131\u011f\u0131 kolayl\u0131\u011f\u0131, daha eski derleyicilerde taklit etmek i\u00e7in geli\u015fmi\u015f makro tekniklerine ba\u015fvurmam\u0131z gerekecektir.<\/p>\n<h2>C23 \u00d6ncesi <code class=\"language-c\">__VA_OPT__<\/code> Yerine Ge\u00e7en Geli\u015fmi\u015f Teknikler<\/h2>\n<p><code class=\"language-c\">__VA_OPT__<\/code>'un temel i\u015flevi, <code class=\"language-c\">__VA_ARGS__<\/code> bo\u015f oldu\u011funda belirli bir token dizisini geni\u015fletmemek, dolu oldu\u011funda ise geni\u015fletmektir. Bu, \u00f6zellikle <code class=\"language-c\">printf<\/code> benzeri makrolarda format dizisinden sonra gelen virg\u00fcl\u00fc ve de\u011fi\u015fken arg\u00fcmanlar\u0131 ko\u015fullu olarak eklemek i\u00e7in kullan\u0131l\u0131r. C23 ve C++20 \u00f6ncesi derleyicilerde bu yetene\u011fi taklit etmek i\u00e7in birka\u00e7 farkl\u0131 strateji mevcuttur. Her birinin kendine g\u00f6re avantajlar\u0131 ve dezavantajlar\u0131 vard\u0131r ve derleyici deste\u011fi a\u00e7\u0131s\u0131ndan farkl\u0131l\u0131k g\u00f6sterebilirler.<\/p>\n<h3>GNU Uzant\u0131s\u0131 <code class=\"language-c\"><strong>__VA_ARGS__<\/code> ile Basit Bir Ba\u015flang\u0131\u00e7<\/h3>\n<p><\/strong><\/p>\n<p>GNU tabanl\u0131 derleyiciler (GCC ve Clang gibi), <code class=\"language-c\">__VA_OPT__<\/code>'tan \u00e7ok daha \u00f6nce, benzer bir i\u015flevsellik sunan <code class=\"language-c\"><strong>__VA_ARGS__<\/code> adl\u0131 \u00f6zel bir uzant\u0131ya sahipti. Bu uzant\u0131, e\u011fer <code class=\"language-c\">__VA_ARGS__<\/code> bo\u015fsa, <code class=\"language-c\">##<\/code> operat\u00f6r\u00fcn\u00fcn solundaki virg\u00fcl\u00fc kald\u0131r\u0131r. Bu, <code class=\"language-c\">__VA_OPT__<\/code>'un sa\u011flad\u0131\u011f\u0131 esnekli\u011fe en yak\u0131n ve en basit \u00e7\u00f6z\u00fcmlerden biridir, ancak ta\u015f\u0131nabilirlik a\u00e7\u0131s\u0131ndan bir k\u0131s\u0131tlamaya sahiptir \u00e7\u00fcnk\u00fc standart bir \u00f6zellik de\u011fildir.<\/p>\n<p><\/strong><\/p>\n<p>\u00d6rne\u011fimize geri d\u00f6nersek, <code class=\"language-c\"><strong>__VA_ARGS__<\/code> ile sondaki virg\u00fcl sorununu nas\u0131l \u00e7\u00f6zebilece\u011fimizi g\u00f6relim:<\/p>\n<p><\/strong><\/p>\n<div class=\"code-block\">\n<pre><code class=\"language-c\">\n#include <stdio.h>\n\n\/\/ GNU uzant\u0131s\u0131 kullan\u0131larak daha esnek bir makro\n#define DEBUG_LOG_GNU(format, ...) \\\n    printf(\"DEBUG: \" format \"\\n\" <strong>__VA_ARGS__)<\/strong>\n\nint main() {\n    int y = 20;\n    DEBUG_LOG_GNU(\"y degeri: %d\", y);      \/\/ \u00c7\u0131kt\u0131: DEBUG: y degeri: 20\n    DEBUG_LOG_GNU(\"Basit bir mesaj (GNU)\"); \/\/ \u00c7\u0131kt\u0131: DEBUG: Basit bir mesaj (GNU)\n    return 0;\n}\n        <\/pre>\n<p><\/code>\n    <\/div>\n<p>Bu \u00e7\u00f6z\u00fcm, GNU derleyicileri i\u00e7in olduk\u00e7a pratiktir ve \u00e7ok say\u0131da projede yayg\u0131n olarak kullan\u0131lmaktad\u0131r. <code class=\"language-c\">DEBUG_LOG_GNU(\"Basit bir mesaj (GNU)\");<\/code> \u00e7a\u011fr\u0131s\u0131nda, <code class=\"language-c\">__VA_ARGS__<\/code> bo\u015f oldu\u011fundan <code class=\"language-c\"><strong><\/code> operat\u00f6r\u00fc <code class=\"language-c\">\"\\n\"<\/code> ile <code class=\"language-c\">__VA_ARGS__<\/code> aras\u0131ndaki virg\u00fcl\u00fc kald\u0131r\u0131r ve <code class=\"language-c\">printf(\"DEBUG: Basit bir mesaj (GNU)\\n\")<\/code> \u015feklinde do\u011fru bir geni\u015fleme sa\u011flar. Ancak bu uzant\u0131 Microsoft Visual C++ derleyicisi gibi di\u011fer derleyicilerde desteklenmez, bu da ta\u015f\u0131nabilir uygulamalar geli\u015ftirenler i\u00e7in bir dezavantaj olu\u015fturur. Bu nedenle, daha evrensel bir \u00e7\u00f6z\u00fcm aray\u0131\u015f\u0131 devam eder.<\/p>\n<p><\/strong><\/p>\n<h3>Ta\u015f\u0131nabilir \u00c7\u00f6z\u00fcmler: Makro A\u015f\u0131r\u0131 Y\u00fckleme ve Arg\u00fcman Sayma Hileleri<\/h3>\n<p>GNU uzant\u0131s\u0131n\u0131n ta\u015f\u0131nabilirlik sorunlar\u0131 nedeniyle, t\u00fcm derleyicilerde \u00e7al\u0131\u015facak daha karma\u015f\u0131k ama standartlara uygun yakla\u015f\u0131mlar geli\u015ftirmek gerekir. Bu yakla\u015f\u0131mlardan en yayg\u0131n olan\u0131, makro a\u015f\u0131r\u0131 y\u00fcklemesi ve arg\u00fcman sayma tekniklerini birle\u015ftirmektir. Temel fikir, de\u011fi\u015fken arg\u00fcmanlar\u0131n say\u0131s\u0131n\u0131 belirleyerek, farkl\u0131 arg\u00fcman say\u0131lar\u0131 i\u00e7in farkl\u0131 makro tan\u0131mlar\u0131na ge\u00e7i\u015f yapmakt\u0131r. Bu sayede, <code class=\"language-c\">__VA_ARGS__<\/code> bo\u015f oldu\u011funda (yani s\u0131f\u0131r arg\u00fcman durumunda) farkl\u0131 bir makro, bir veya daha fazla arg\u00fcman oldu\u011funda ise ba\u015fka bir makro \u00e7a\u011f\u0131rabiliriz.<\/p>\n<p>Bu stratejiyi uygulamak i\u00e7in genellikle a\u015fa\u011f\u0131daki ad\u0131mlar\u0131 izleriz:<\/p>\n<ol>\n<li>Arg\u00fcman say\u0131s\u0131n\u0131 hesaplayan bir makro hilesi olu\u015fturmak. Bu, genellikle bo\u015f bir arg\u00fcman listesini tespit etmek i\u00e7in bir dizi sabit ve \u00f6zel bir 'getter' makrosu kullanmay\u0131 i\u00e7erir.<\/li>\n<li>Bu say\u0131ya g\u00f6re farkl\u0131 makro uygulamalar\u0131na (\u00f6rne\u011fin <code class=\"language-c\">MY_MACRO_0<\/code>, <code class=\"language-c\">MY_MACRO_1<\/code>, <code class=\"language-c\">MY_MACRO_N<\/code> gibi) y\u00f6nlendiren bir 'dispatcher' makrosu tan\u0131mlamak.<\/li>\n<li>Her bir say\u0131ya \u00f6zel makroda istenen davran\u0131\u015f\u0131 kodlamak.<\/li>\n<\/ol>\n<p>\u0130\u015fte bu karma\u015f\u0131k yap\u0131n\u0131n basitle\u015ftirilmi\u015f bir \u00f6rne\u011fi:<\/p>\n<div class=\"code-block\">\n<pre><code class=\"language-c\">\n#include <stdio.h>\n\n\/\/ Yard\u0131mc\u0131 makrolar: Makro arg\u00fcmanlar\u0131n\u0131 saymak i\u00e7in\n#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N\n#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)\n\n\/\/ Makro isimlerini birle\u015ftirmek i\u00e7in\n#define CAT(A, B) A <strong>B<\/strong>\n#define CAT_INDIRECT(A, B) CAT(A, B)\n\n\/\/ Dispatcher makrosu\n#define CHOOSE_MACRO_OVERLOAD(name, ...) \\\n    CAT_INDIRECT(name, VA_NARGS(__VA_ARGS__))(__VA_ARGS__)\n\n\/\/ Uygulama makrolar\u0131\n#define MY_LOG_IMPL_0() \\\n    printf(\"Sadece bir mesaj.\\n\")\n\n#define MY_LOG_IMPL_1(format_str) \\\n    printf(format_str \"\\n\")\n\n#define MY_LOG_IMPL_2(format_str, arg1) \\\n    printf(format_str \"\\n\", arg1)\n\n#define MY_LOG_IMPL_3(format_str, arg1, arg2) \\\n    printf(format_str \"\\n\", arg1, arg2)\n\n\/\/ Genel MY_LOG makrosu\n#define MY_LOG(...) CHOOSE_MACRO_OVERLOAD(MY_LOG_IMPL_, __VA_ARGS__)\n\nint main() {\n    int val = 123;\n    const char* text = \"Merhaba Dunya\";\n\n    MY_LOG();                       \/\/ \u00c7\u0131kt\u0131: Sadece bir mesaj.\n    MY_LOG(\"Bir format dizisi.\");     \/\/ \u00c7\u0131kt\u0131: Bir format dizisi.\n    MY_LOG(\"De\u011fer: %d\", val);        \/\/ \u00c7\u0131kt\u0131: De\u011fer: 123\n    MY_LOG(\"Metin: %s, De\u011fer: %d\", text, val); \/\/ \u00c7\u0131kt\u0131: Metin: Merhaba Dunya, De\u011fer: 123\n    return 0;\n}\n        <\/pre>\n<p><\/code>\n    <\/div>\n<p>Bu \u00f6rnekte, <code class=\"language-c\">VA_NARGS<\/code> makrosu, kendisine verilen arg\u00fcmanlar\u0131n say\u0131s\u0131n\u0131 hesaplar. <code class=\"language-c\">CHOOSE_MACRO_OVERLOAD<\/code> ise bu say\u0131y\u0131 kullanarak <code class=\"language-c\">MY_LOG_IMPL_0<\/code> (hi\u00e7 arg\u00fcman yoksa), <code class=\"language-c\">MY_LOG_IMPL_1<\/code> (bir arg\u00fcman varsa) vb. gibi do\u011fru uygulama makrosunu se\u00e7er. Bu teknik, t\u00fcm standart C ve C++ derleyicilerinde \u00e7al\u0131\u015f\u0131r ve <code class=\"language-c\">__VA_OPT__<\/code>'un sundu\u011fu esnekli\u011fi taklit etmek i\u00e7in g\u00fc\u00e7l\u00fc bir yoldur. Dezavantaj\u0131 ise, desteklenecek maksimum arg\u00fcman say\u0131s\u0131na g\u00f6re <code class=\"language-c\">VA_NARGS_IMPL<\/code> ve <code class=\"language-c\">MY_LOG_IMPL_N<\/code> makrolar\u0131n\u0131n tekrarl\u0131 bir \u015fekilde tan\u0131mlanmas\u0131 gerekmesidir, ki bu da kod karma\u015f\u0131kl\u0131\u011f\u0131n\u0131 art\u0131r\u0131r.<\/p>\n<div class=\"tip\">\n        Uzman \u0130pucu: Arg\u00fcman sayma makrolar\u0131, genellikle 64 adede kadar arg\u00fcman\u0131 destekleyecek \u015fekilde geni\u015fletilebilir. Daha fazla esneklik i\u00e7in, arg\u00fcman say\u0131s\u0131n\u0131 do\u011frudan <code class=\"language-c\">__VA_ARGS__<\/code>'\u0131 kullanarak de\u011fil, \u00f6zel bir \u00f6n arg\u00fcman hilesiyle tespit eden daha karma\u015f\u0131k \u015fablonlar da mevcuttur. Ancak temel prensip ayn\u0131 kal\u0131r: do\u011fru makroya y\u00f6nlendirme.\n    <\/div>\n<h3>Alternatif Yakla\u015f\u0131mlar: \u0130kili Durum ve \u00d6zel Makro Yap\u0131lar\u0131<\/h3>\n<p>Yukar\u0131daki arg\u00fcman sayma yakla\u015f\u0131m\u0131 olduk\u00e7a genel ve ta\u015f\u0131nabilirdir, ancak belirli senaryolarda daha basit veya derleyiciye \u00f6zel optimizasyonlar arayabiliriz. \u00d6zellikle Microsoft Visual C++ derleyicisi gibi <code class=\"language-c\"><strong>__VA_ARGS__<\/code> uzant\u0131s\u0131n\u0131 desteklemeyen platformlarda, bazen farkl\u0131 bir stratejiye ihtiya\u00e7 duyulur. MSVC i\u00e7in bazen <code class=\"language-c\">__VA_ARGS__<\/code>'\u0131 bir parantez i\u00e7inde sarmak gibi \"d\u00fczeltme\" mekanizmalar\u0131 i\u015fe yarasa da, bu \u00e7o\u011fu zaman <code class=\"language-c\">__VA_OPT__<\/code>'un tam i\u015flevselli\u011fini taklit etmekte yetersiz kal\u0131r.<\/p>\n<p><\/strong><\/p>\n<p>Bir di\u011fer yayg\u0131n \"ikili durum\" yakla\u015f\u0131m\u0131, makroya her zaman fazladan bir dummy (kukla) arg\u00fcman ge\u00e7irmek ve bu arg\u00fcman\u0131 kullanarak <code class=\"language-c\">__VA_ARGS__<\/code>'\u0131n ger\u00e7ekten bo\u015f olup olmad\u0131\u011f\u0131n\u0131 dolayl\u0131 yoldan tespit etmektir. Ancak bu, <code class=\"language-c\">printf<\/code> benzeri bir formatta virg\u00fcl sorununu do\u011frudan \u00e7\u00f6zmez. Bunun yerine, bir makronun davran\u0131\u015f\u0131n\u0131 tamamen de\u011fi\u015ftirmek i\u00e7in kullan\u0131labilir.<\/p>\n<p>Ger\u00e7ek <code class=\"language-c\">__VA_OPT__<\/code> davran\u0131\u015f\u0131na en yak\u0131n ta\u015f\u0131nabilir taklit, genellikle arg\u00fcman sayma ve \u00f6zel bir <code>COMMA_IF_ARGS<\/code> makrosunu birle\u015ftirmeyi i\u00e7erir. Ancak, bu tarz bir <code>COMMA_IF_ARGS<\/code> makrosunun tamamen ta\u015f\u0131nabilir olmas\u0131, \u00f6ni\u015flemcinin token birle\u015ftirme kurallar\u0131 nedeniyle olduk\u00e7a zordur ve genellikle yine derleyici uzant\u0131lar\u0131na (<code><strong><\/code> gibi) veya \u00e7ok karma\u015f\u0131k token tespiti mekanizmalar\u0131na ihtiya\u00e7 duyar. Bu nedenle, \u00e7o\u011fu geli\u015ftirici ya GNU uzant\u0131s\u0131n\u0131 kullanmay\u0131 tercih eder ya da yukar\u0131da bahsedilen arg\u00fcman sayma ve a\u015f\u0131r\u0131 y\u00fckleme tekni\u011fine g\u00fcvenir.<\/p>\n<p><\/strong><\/p>\n<p>Yine de, belirli durumlarda daha basit bir ikili durum ayr\u0131m\u0131 yapmak isteyebiliriz. \u00d6rne\u011fin, bir makronun sadece bir mesaj m\u0131 yoksa formatl\u0131 bir mesaj m\u0131 basaca\u011f\u0131n\u0131 belirlemek i\u00e7in:<\/p>\n<div class=\"code-block\">\n<pre><code class=\"language-c\">\n#include <stdio.h>\n\n\/\/ Basit makro a\u015f\u0131r\u0131 y\u00fckleme i\u00e7in yard\u0131mc\u0131\n#define GET_MACRO(_1, _2, _3, _4, NAME, ...) NAME\n#define LOG_MESSAGE_N(format, ...) printf(\"[MESAJ]: \" format \"\\n\", __VA_ARGS__)\n#define LOG_MESSAGE_0(message) printf(\"[MESAJ]: %s\\n\", message) \/\/ Tek arg\u00fcman bekler\n\n\/\/ Kullan\u0131m i\u00e7in ana makro. E\u011fer 1 arg\u00fcman varsa LOG_MESSAGE_0'a, di\u011fer t\u00fcrl\u00fc LOG_MESSAGE_N'ye y\u00f6nlendirir.\n\/\/ Bu \u00f6rnek, arg\u00fcman say\u0131s\u0131n\u0131n 1 oldu\u011fu \u00f6zel durumu i\u015flemek i\u00e7in tasarlanm\u0131\u015ft\u0131r.\n\/\/ __VA_ARGS__ bo\u015fken sorun \u00e7\u0131karabilir, bu y\u00fczden dikkatli kullan\u0131lmal\u0131.\n\/\/ As\u0131l hedef: E\u011fer __VA_ARGS__ bo\u015fsa bir makro, de\u011filse di\u011fer makro.\n\/\/ Daha g\u00fcvenli ta\u015f\u0131nabilir yakla\u015f\u0131m:\n\n#define CHOOSE_LOG_MACRO_(_0, _1, _2, _3, _4, NAME, ...) NAME\n#define CHOOSE_LOG_MACRO(...) CHOOSE_LOG_MACRO_(__VA_ARGS__, LOG_FORMAT_ARGS, LOG_FORMAT_ARGS, LOG_FORMAT_ARGS, LOG_FORMAT_ARGS, LOG_NO_ARGS)\n\n#define LOG_NO_ARGS(msg) printf(\"[LOG]: %s\\n\", msg)\n#define LOG_FORMAT_ARGS(fmt, ...) printf(\"[LOG]: \" fmt \"\\n\", __VA_ARGS__)\n\n\/\/ Bu y\u00f6ntem, ilk arg\u00fcman\u0131 kullanarak dispatch yapmaya \u00e7al\u0131\u015f\u0131r.\n\/\/ Ger\u00e7ek __VA_OPT__ benzetimi i\u00e7in yine arg\u00fcman sayma daha g\u00fcvenli.\n\/\/ Basit bir \u00f6rnek olarak:\n#define MY_DEBUG(...) \\\n    do { \\\n        if (sizeof((char[]){0, <strong>__VA_ARGS__}) > 1) { \/* GNU\/Clang \u00f6zel kontrol *\/ \\<\/strong>\n            printf(\"DEBUG: \" __VA_ARGS__); \\\n        } else { \\\n            printf(\"DEBUG: Bir hata olu\u015ftu.\\n\"); \\\n        } \\\n    } while(0)\n\/\/ Yukar\u0131daki sizeof hilesi de platforma ba\u011f\u0131ml\u0131d\u0131r ve ta\u015f\u0131nabilir de\u011fildir.\n\n\/\/ \u00d6zetle, en ta\u015f\u0131nabilir ve pratik yol, arg\u00fcman sayma ile makro a\u015f\u0131r\u0131 y\u00fcklemedir.\n\/\/ GNU uzant\u0131s\u0131 mevcutsa, <code><strong>__VA_ARGS__<\/code> en kolay yoldur.<\/strong>\n        <\/pre>\n<p><\/code>\n    <\/div>\n<p>Bu b\u00f6l\u00fcm, karma\u015f\u0131k makro yakla\u015f\u0131mlar\u0131n\u0131 \u00f6zetlemekte ve <code class=\"language-c\">__VA_OPT__<\/code>'un yerine ge\u00e7ecek en pratik ve ta\u015f\u0131nabilir \u00e7\u00f6z\u00fcm olarak arg\u00fcman sayma y\u00f6ntemini vurgulamaktad\u0131r. Di\u011fer yakla\u015f\u0131mlar genellikle derleyiciye \u00f6zg\u00fc hilelere veya a\u015f\u0131r\u0131 karma\u015f\u0131kl\u0131\u011fa yol a\u00e7ar.<\/p>\n<h2>Ger\u00e7ek D\u00fcnya Uygulamalar\u0131 ve Pratik Vaka Analizleri<\/h2>\n<p>\u015eimdiye kadar \u00f6\u011frendi\u011fimiz geli\u015fmi\u015f makro tekniklerini, ger\u00e7ek d\u00fcnyada s\u0131k\u00e7a kar\u015f\u0131la\u015f\u0131lan senaryolara uygulayal\u0131m. Bu vaka analizleri, makrolar\u0131n sadece bir s\u00f6zdizimi \u015fekerinden ibaret olmad\u0131\u011f\u0131n\u0131, ayn\u0131 zamanda kod kalitesini, esnekli\u011fini ve hata ay\u0131klama s\u00fcre\u00e7lerini nas\u0131l iyile\u015ftirebilece\u011fini g\u00f6sterecektir.<\/p>\n<h3>Geli\u015fmi\u015f Bir Loglama Sistemi Nas\u0131l Olu\u015fturulur?<\/h3>\n<p>Loglama, herhangi bir yaz\u0131l\u0131m projesinin ayr\u0131lmaz bir par\u00e7as\u0131d\u0131r. Uygulama \u00e7al\u0131\u015f\u0131rken neler oldu\u011funu anlamam\u0131z\u0131, hatalar\u0131 tespit etmemizi ve performans darbo\u011fazlar\u0131n\u0131 bulmam\u0131z\u0131 sa\u011flar. Geli\u015fmi\u015f makro teknikleri kullanarak, hem basit mesajlar\u0131 hem de formatl\u0131 \u00e7\u0131kt\u0131lar\u0131 destekleyen esnek bir loglama sistemi olu\u015fturabiliriz. B\u00f6yle bir sistem, <code class=\"language-c\">__VA_OPT__<\/code>'un sa\u011flad\u0131\u011f\u0131 gibi, iste\u011fe ba\u011fl\u0131 arg\u00fcmanlar\u0131 sorunsuz bir \u015fekilde i\u015fleyebilmelidir.<\/p>\n<p>Yukar\u0131da bahsetti\u011fimiz arg\u00fcman sayma ve makro a\u015f\u0131r\u0131 y\u00fckleme prensiplerini kullanarak, farkl\u0131 log seviyeleri (bilgi, uyar\u0131, hata) i\u00e7in \u00f6zelle\u015ftirilebilir bir loglama makrosu tasarlayal\u0131m. Bu makro, arg\u00fcman verilmedi\u011finde sadece sabit bir mesaj basacak, arg\u00fcman verildi\u011finde ise <code class=\"language-c\">printf<\/code> benzeri bir formatla \u00e7\u0131kt\u0131 \u00fcretecektir.<\/p>\n<div class=\"code-block\">\n<pre><code class=\"language-c\">\n#include <stdio.h>\n#include <time.h> \/\/ Zaman damgas\u0131 i\u00e7in\n\n\/\/ --- Arg\u00fcman Sayma Yard\u0131mc\u0131 Makrolar\u0131 ---\n#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N\n#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)\n#define CAT(A, B) A <strong>B<\/strong>\n#define CAT_INDIRECT(A, B) CAT(A, B)\n#define CHOOSE_MACRO_OVERLOAD(name, ...) \\\n    CAT_INDIRECT(name, VA_NARGS(__VA_ARGS__))(__VA_ARGS__)\n\n\/\/ --- Zaman Damgas\u0131 Fonksiyonu ---\nstatic inline void print_timestamp() {\n    time_t timer;\n    char buffer[26];\n    struct tm* tm_info;\n    time(&timer);\n    tm_info = localtime(&timer);\n    strftime(buffer, 26, \"%Y-%m-%d %H:%M:%S\", tm_info);\n    printf(\"[%s] \", buffer);\n}\n\n\/\/ --- Loglama Makrolar\u0131 ---\n#define LOG_MESSAGE_IMPL_0(level_str) \\\n    do { \\\n        print_timestamp(); \\\n        printf(\"[%s] Genel mesaj\\n\", level_str); \\\n    } while(0)\n\n#define LOG_MESSAGE_IMPL_1(level_str, msg) \\\n    do { \\\n        print_timestamp(); \\\n        printf(\"[%s] %s\\n\", level_str, msg); \\\n    } while(0)\n\n\/\/ 2 arg\u00fcmanl\u0131 (format + 1 de\u011fi\u015fken arg\u00fcman)\n#define LOG_MESSAGE_IMPL_2(level_str, format, arg1) \\\n    do { \\\n        print_timestamp(); \\\n        printf(\"[%s] \" format \"\\n\", level_str, arg1); \\\n    } while(0)\n\n\/\/ n arg\u00fcmanl\u0131 (format + n-1 de\u011fi\u015fken arg\u00fcman)\n\/\/ Daha fazla arg\u00fcman i\u00e7in LOG_MESSAGE_IMPL_N'i geni\u015fletmek gerekir.\n\/\/ \u00d6rne\u011fin, 3 arg\u00fcman i\u00e7in (level_str, format, arg1, arg2):\n#define LOG_MESSAGE_IMPL_3(level_str, format, arg1, arg2) \\\n    do { \\\n        print_timestamp(); \\\n        printf(\"[%s] \" format \"\\n\", level_str, arg1, arg2); \\\n    } while(0)\n\n\/\/ Ana LOG makrosu. \u0130lk arg\u00fcman\u0131 log seviyesi olarak al\u0131r, geri kalanlar format ve de\u011fi\u015fken arg\u00fcmanlard\u0131r.\n\/\/ NOT: Bu setup'ta, LOG(LEVEL, ...) \u015feklinde \u00e7a\u011f\u0131rd\u0131\u011f\u0131m\u0131zda,\n\/\/ VA_NARGS(__VA_ARGS__) asl\u0131nda LEVEL'\u0131 da sayar.\n\/\/ Bu y\u00fczden arg\u00fcman say\u0131s\u0131n\u0131 1 eksik hesaplamam\u0131z laz\u0131m, veya \u00f6zel bir dispatcher yazmam\u0131z laz\u0131m.\n\/\/ Daha basit bir yakla\u015f\u0131m i\u00e7in: level_str'\u0131 makroya dahil edelim ve _NARGS() k\u0131sm\u0131na sadece format ve VA_ARGS'\u0131 verelim.\n#define LOG(level_str, ...) \\\n    CHOOSE_MACRO_OVERLOAD(LOG_MESSAGE_IMPL_, 1 + VA_NARGS(__VA_ARGS__)) (level_str, __VA_ARGS__)\n\n\nint main() {\n    int count = 5;\n    const char* user = \"Alice\";\n\n    \/\/ 0 arg\u00fcman i\u00e7in (sadece level_str ve bo\u015f VA_ARGS, toplam 1 arg\u00fcman)\n    \/\/ Bu \u00e7a\u011fr\u0131 asl\u0131nda LOG_MESSAGE_IMPL_1'e gidecek ve \"INFO\"yu format olarak kullanacak.\n    \/\/ __VA_OPT__ olmadan bu durumu y\u00f6netmek zordur.\n    \/\/ E\u011fer seviye string'ini de makro geni\u015fletmesinin i\u00e7ine almak istersek:\n    printf(\"--- Basit Log Denemeleri ---\\n\");\n    printf(\"Bu k\u0131s\u0131mda, LOG makrosunun ilk arg\u00fcman\u0131 'level_str' her zaman mevcut.\\n\");\n    printf(\"Bu nedenle VA_NARGS(__VA_ARGS__) sadece 'format' ve sonras\u0131 i\u00e7in ge\u00e7erli.\\n\");\n    printf(\"LOG makromuzu yeniden d\u00fczenleyelim:\\n\\n\");\n\n#undef CHOOSE_MACRO_OVERLOAD\n#undef LOG\n#undef LOG_MESSAGE_IMPL_0\n#undef LOG_MESSAGE_IMPL_1\n#undef LOG_MESSAGE_IMPL_2\n#undef LOG_MESSAGE_IMPL_3\n\n\/\/ Yeni, daha do\u011fru bir dispatcher ve log makrosu\n#define VA_NARGS_MINUS_ONE(...) VA_NARGS_IMPL(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)\n\/\/ E\u011fer hi\u00e7 VA_ARGS yoksa NARGS_MINUS_ONE 0 d\u00f6nd\u00fcr\u00fcr, format varsa 1, vs.\n\/\/ Bu y\u00fczden LOG_MESSAGE_IMPL_X isimlerini yeniden d\u00fczenleyelim.\n\n#define LOG_IMPL_0(level_str) \\\n    do { \\\n        print_timestamp(); \\\n        printf(\"[%s] Genel mesaj\\n\", level_str); \\\n    } while(0)\n\n#define LOG_IMPL_1(level_str, format) \\\n    do { \\\n        print_timestamp(); \\\n        printf(\"[%s] %s\\n\", level_str, format); \\\n    } while(0)\n\n#define LOG_IMPL_2(level_str, format, arg1) \\\n    do { \\\n        print_timestamp(); \\\n        printf(\"[%s] \" format \"\\n\", level_str, arg1); \\\n    } while(0)\n\n#define LOG_IMPL_3(level_str, format, arg1, arg2) \\\n    do { \\\n        print_timestamp(); \\\n        printf(\"[%s] \" format \"\\n\", level_str, arg1, arg2); \\\n    } while(0)\n\n\/\/ Ana LOG makrosu. level_str her zaman var. VA_ARGS'\u0131n geri kalan\u0131n\u0131 say\u0131yoruz.\n\/\/ CHOOSE_MACRO_OVERLOAD makrosunu sadece __VA_ARGS__ i\u00e7in kullanarak ve level_str'\u0131 ayr\u0131 ge\u00e7irerek.\n#define LOG(level_str, ...) \\\n    CAT_INDIRECT(LOG_IMPL_, VA_NARGS(__VA_ARGS__)) (level_str, <strong>__VA_ARGS__)<\/strong>\n    \/\/ Bu hala GNU'ya ba\u011f\u0131ml\u0131 (<code><strong>__VA_ARGS__<\/code>). Tamamen ta\u015f\u0131nabilir i\u00e7in biraz daha farkl\u0131.<\/strong>\n    \/\/ Tamamen ta\u015f\u0131nabilir \u00e7\u00f6z\u00fcm i\u00e7in:\n    \/\/ #define LOG(level_str, ...) \\\n    \/\/     CAT_INDIRECT(LOG_IMPL_, VA_NARGS(__VA_ARGS__))(level_str, __VA_ARGS__)\n    \/\/ E\u011fer VA_NARGS 0 ise, bu LOG_IMPL_0(level_str, ) olur ki bu hatad\u0131r.\n    \/\/ Dolay\u0131s\u0131yla, dispatcher\u0131n bo\u015f VA_ARGS durumunda ayr\u0131 bir makroya y\u00f6nlendirmesi gerekiyor.\n    \/\/ Bu, \u00f6nceki CHOOSE_MACRO_OVERLOAD yakla\u015f\u0131m\u0131n\u0131 daha da dikkatli kullanmay\u0131 gerektirir.\n\n\/\/ Ta\u015f\u0131nabilir ve sa\u011flam LOG makrosu (\u00f6nceki arg\u00fcman sayma mant\u0131\u011f\u0131na dayan\u0131r)\n#define LOG_DISPATCHER(level_str, N, ...) \\\n    CAT_INDIRECT(LOG_IMPL_, N)(level_str, <strong>__VA_ARGS__)<\/strong>\n\n#define LOG_PORTABLE(level_str, ...) \\\n    LOG_DISPATCHER(level_str, VA_NARGS(__VA_ARGS__), <strong>__VA_ARGS__)<\/strong>\n    \/\/ Hala <strong>__VA_ARGS__ kullan\u0131l\u0131yor.<\/strong>\n    \/\/ __VA_OPT__ yerine ge\u00e7me karma\u015f\u0131kl\u0131\u011f\u0131 burada ortaya \u00e7\u0131k\u0131yor.\n    \/\/ Saf C standard\u0131nda, arg\u00fcman say\u0131s\u0131na g\u00f6re dispatch etmek en iyisidir.\n    \/\/ Bir \u00f6nceki MY_LOG \u00f6rne\u011findeki gibi, direkt format ve arg\u00fcmanlar\u0131 sayan bir yap\u0131.\n    \/\/ <code>level_str<\/code>'\u0131 da arg\u00fcman olarak sayarak ilerleyelim.\n\n#undef MY_LOG_IMPL_0\n#undef MY_LOG_IMPL_1\n#undef MY_LOG_IMPL_2\n#undef MY_LOG_IMPL_3\n#undef MY_LOG\n\n#define MY_LOG_IMPL_0() \\\n    do { \\\n        print_timestamp(); \\\n        printf(\"[GENEL] Bir olay meydana geldi.\\n\"); \\\n    } while(0)\n\n#define MY_LOG_IMPL_1(level_str) \\\n    do { \\\n        print_timestamp(); \\\n        printf(\"[%s] Bir olay meydana geldi.\\n\", level_str); \\\n    } while(0)\n\n#define MY_LOG_IMPL_2(level_str, format) \\\n    do { \\\n        print_timestamp(); \\\n        printf(\"[%s] %s\\n\", level_str, format); \\\n    } while(0)\n\n#define MY_LOG_IMPL_3(level_str, format, arg1) \\\n    do { \\\n        print_timestamp(); \\\n        printf(\"[%s] \" format \"\\n\", level_str, arg1); \\\n    } while(0)\n\n#define MY_LOG_IMPL_4(level_str, format, arg1, arg2) \\\n    do { \\\n        print_timestamp(); \\\n        printf(\"[%s] \" format \"\\n\", level_str, arg1, arg2); \\\n    } while(0)\n\n#define MY_LOG(...) CHOOSE_MACRO_OVERLOAD(MY_LOG_IMPL_, __VA_ARGS__)\n\n    MY_LOG();                                         \/\/ \u00c7\u0131kt\u0131: [GENEL] Bir olay meydana geldi.\n    MY_LOG(\"INFO\");                                   \/\/ \u00c7\u0131kt\u0131: [INFO] Bir olay meydana geldi.\n    MY_LOG(\"WARN\", \"Disk alan\u0131 azal\u0131yor.\");             \/\/ \u00c7\u0131kt\u0131: [WARN] Disk alan\u0131 azal\u0131yor.\n    MY_LOG(\"ERROR\", \"Kullan\u0131c\u0131 '%s' bulunamad\u0131.\", user); \/\/ \u00c7\u0131kt\u0131: [ERROR] Kullan\u0131c\u0131 'Alice' bulunamad\u0131.\n    MY_LOG(\"DEBUG\", \"Saya\u00e7: %d\", count);              \/\/ \u00c7\u0131kt\u0131: [DEBUG] Saya\u00e7: 5\n    MY_LOG(\"VERBOSE\", \"Fonksiyon %s \u00e7a\u011fr\u0131ld\u0131, de\u011fer: %d.\", __func__, count); \/\/ \u00c7\u0131kt\u0131: [VERBOSE] Fonksiyon main \u00e7a\u011fr\u0131ld\u0131, de\u011fer: 5.\n\n    printf(\"\\n--- GNU Uzant\u0131s\u0131 ile Log Denemeleri ---\\n\");\n    #ifdef __GNUC__\n    #define LOG_GNU(level_str, format, ...) \\\n        do { \\\n            print_timestamp(); \\\n            printf(\"[%s] \" format \"\\n\" <strong>__VA_ARGS__); \\<\/strong>\n        } while(0)\n\n    LOG_GNU(\"INFO\", \"Sadece bir mesaj.\");\n    LOG_GNU(\"WARN\", \"Haf\u0131za kullan\u0131m\u0131: %d%%\", 85);\n    #else\n    printf(\"GNU uzant\u0131s\u0131 mevcut de\u011fil, \u00f6rnek atland\u0131.\\n\");\n    #endif\n\n    return 0;\n}\n        <\/pre>\n<p><\/code>\n    <\/div>\n<p>Bu karma\u015f\u0131k loglama makrosu \u00f6rne\u011fi, <code class=\"language-c\">__VA_OPT__<\/code>'un eksikli\u011fini gidermek i\u00e7in arg\u00fcman sayma ve makro a\u015f\u0131r\u0131 y\u00fckleme y\u00f6nteminin nas\u0131l kullan\u0131ld\u0131\u011f\u0131n\u0131 g\u00f6stermektedir. <code class=\"language-c\">MY_LOG()<\/code> \u00e7a\u011fr\u0131s\u0131 s\u0131f\u0131r arg\u00fcman\u0131, <code class=\"language-c\">MY_LOG(\"INFO\")<\/code> bir arg\u00fcman\u0131 ve <code class=\"language-c\">MY_LOG(\"ERROR\", \"...\", var)<\/code> \u00e7oklu arg\u00fcmanlar\u0131 i\u015fler. Her durumda, do\u011fru <code class=\"language-c\">MY_LOG_IMPL_N<\/code> makrosuna y\u00f6nlendirilerek hatas\u0131z bir \u00e7\u0131kt\u0131 elde edilir. Bu, eski standartlarda bile g\u00fc\u00e7l\u00fc ve esnek bir loglama sistemi kurmak i\u00e7in sa\u011flam bir temel sunar.<\/p>\n<h3>Ak\u0131ll\u0131 Assert ve Hata Ay\u0131klama Makrolar\u0131<\/h3>\n<p>Assert mekanizmalar\u0131, \u00e7al\u0131\u015fma zaman\u0131nda belirli ko\u015fullar\u0131n do\u011fru olup olmad\u0131\u011f\u0131n\u0131 kontrol etmek ve e\u011fer yanl\u0131\u015fsa program\u0131 durdurup hata mesaj\u0131 vermek i\u00e7in kullan\u0131l\u0131r. Geli\u015fmi\u015f makrolar sayesinde, standart <code class=\"language-c\">assert()<\/code> fonksiyonundan daha esnek, iste\u011fe ba\u011fl\u0131 hata mesajlar\u0131 veya ba\u011flam bilgileri sa\u011flayabilen ak\u0131ll\u0131 assert makrolar\u0131 olu\u015fturabiliriz. Bu, <code class=\"language-c\">__VA_OPT__<\/code>'un sa\u011flad\u0131\u011f\u0131 gibi, hata durumunda ek bilgi iletmeyi kolayla\u015ft\u0131r\u0131r.<\/p>\n<div class=\"code-block\">\n<pre><code class=\"language-c\">\n#include <stdio.h>\n#include <stdlib.h> \/\/ exit() i\u00e7in\n\n#ifdef DEBUG_MODE\n\n\/\/ --- Arg\u00fcman Sayma Yard\u0131mc\u0131 Makrolar\u0131 ---\n\/\/ VA_NARGS, CAT, CAT_INDIRECT, CHOOSE_MACRO_OVERLOAD \u00f6nceki \u00f6rnekten al\u0131nm\u0131\u015ft\u0131r.\n\/\/ Tekrar tan\u0131mlanmad\u0131\u011f\u0131 varsay\u0131l\u0131r.\n\n\/\/ Assert uygulama makrolar\u0131\n#define CUSTOM_ASSERT_IMPL_1(condition) \\\n    do { \\\n        if (!(condition)) { \\\n            fprintf(stderr, \"ASSERTION FAILED: %s (Dosya: %s, Sat\u0131r: %d)\\n\", \\\n                    #condition, __FILE__, __LINE__); \\\n            exit(EXIT_FAILURE); \\\n        } \\\n    } while(0)\n\n#define CUSTOM_ASSERT_IMPL_2(condition, msg) \\\n    do { \\\n        if (!(condition)) { \\\n            fprintf(stderr, \"ASSERTION FAILED: %s (Dosya: %s, Sat\u0131r: %d) - Mesaj: %s\\n\", \\\n                    #condition, __FILE__, __LINE__, msg); \\\n            exit(EXIT_FAILURE); \\\n        } \\\n    } while(0)\n\n#define CUSTOM_ASSERT_IMPL_3(condition, format, arg1) \\\n    do { \\\n        if (!(condition)) { \\\n            fprintf(stderr, \"ASSERTION FAILED: %s (Dosya: %s, Sat\u0131r: %d) - \", \\\n                    #condition, __FILE__, __LINE__); \\\n            fprintf(stderr, format \"\\n\", arg1); \\\n            exit(EXIT_FAILURE); \\\n        } \\\n    } while(0)\n\n\/\/ Ana CUSTOM_ASSERT makrosu\n#define CUSTOM_ASSERT(...) \\\n    CHOOSE_MACRO_OVERLOAD(CUSTOM_ASSERT_IMPL_, __VA_ARGS__)\n\n#else \/\/ DEBUG_MODE tan\u0131ml\u0131 de\u011filse, hi\u00e7bir \u015fey yapma\n#define CUSTOM_ASSERT(...) ((void)0)\n#endif \/\/ DEBUG_MODE\n\nint divide(int a, int b) {\n    CUSTOM_ASSERT(b != 0, \"S\u0131f\u0131ra b\u00f6lme hatas\u0131!\");\n    \/\/ Veya sadece ko\u015ful ile: CUSTOM_ASSERT(b != 0);\n    \/\/ Veya formatl\u0131 mesaj ile: CUSTOM_ASSERT(b != 0, \"B\u00f6lme i\u015flemi i\u00e7in b=%d olamaz\", b);\n    return a \/ b;\n}\n\nint main() {\n    int result = 0;\n    printf(\"--- Ak\u0131ll\u0131 Assert Denemeleri ---\\n\");\n\n    CUSTOM_ASSERT(1 == 1); \/\/ Ba\u015far\u0131l\u0131, \u00e7\u0131kt\u0131 yok\n    printf(\"1 == 1 ko\u015fulu ba\u015far\u0131l\u0131.\\n\");\n\n    \/\/ A\u015fa\u011f\u0131daki \u00e7a\u011fr\u0131, DEBUG_MODE tan\u0131ml\u0131ysa program\u0131 sonland\u0131r\u0131r.\n    \/\/ CUSTOM_ASSERT(0 == 1, \"S\u0131f\u0131r bire e\u015fit de\u011fil!\");\n    \/\/ printf(\"Bu mesaj hi\u00e7bir zaman bas\u0131lmamal\u0131d\u0131r.\\n\");\n\n    result = divide(10, 2);\n    printf(\"10 \/ 2 = %d\\n\", result);\n\n    \/\/ A\u015fa\u011f\u0131daki \u00e7a\u011fr\u0131, DEBUG_MODE tan\u0131ml\u0131ysa program\u0131 sonland\u0131r\u0131r.\n    \/\/ result = divide(10, 0); \/\/ S\u0131f\u0131ra b\u00f6lme hatas\u0131 tetiklenir\n    \/\/ printf(\"Bu mesaj da bas\u0131lmamal\u0131d\u0131r.\\n\");\n\n    return 0;\n}\n        <\/pre>\n<p><\/code>\n    <\/div>\n<p>Bu <code class=\"language-c\">CUSTOM_ASSERT<\/code> makrosu, <code class=\"language-c\">DEBUG_MODE<\/code> derleme bayra\u011f\u0131na g\u00f6re etkinle\u015ftirilip devre d\u0131\u015f\u0131 b\u0131rak\u0131labilir. En \u00f6nemlisi, <code class=\"language-c\">__VA_OPT__<\/code> alternatifi sayesinde, kullan\u0131c\u0131 sadece bir ko\u015ful belirtebilece\u011fi gibi, ek bir hata mesaj\u0131 dizesi veya hatta <code class=\"language-c\">printf<\/code> benzeri formatl\u0131 bir hata mesaj\u0131 da sa\u011flayabilir. Bu esneklik, hata ay\u0131klama s\u0131ras\u0131nda \u00e7ok de\u011ferli ba\u011flamsal bilgilerin yakalanmas\u0131na olanak tan\u0131r ve b\u00f6ylece hata tespitini h\u0131zland\u0131r\u0131r.<\/p>\n<h2>\u0130leri D\u00fczey \u0130pu\u00e7lar\u0131 ve En \u0130yi Uygulamalar: Makro Sihirbazl\u0131\u011f\u0131<\/h2>\n<p>C \u00f6ni\u015flemci makrolar\u0131, do\u011fru kullan\u0131ld\u0131\u011f\u0131nda kodunuza inan\u0131lmaz bir g\u00fc\u00e7 ve esneklik katabilir. Ancak, bu g\u00fc\u00e7le birlikte b\u00fcy\u00fck bir sorumluluk da gelir. Karma\u015f\u0131k makrolar hata ay\u0131klamay\u0131 zorla\u015ft\u0131rabilir ve beklenmedik yan etkilere yol a\u00e7abilir. Bu b\u00f6l\u00fcmde, makrolar\u0131n\u0131z\u0131 daha g\u00fcvenli, okunabilir ve etkili hale getirmek i\u00e7in baz\u0131 ileri d\u00fczey ipu\u00e7lar\u0131n\u0131 ve en iyi uygulamalar\u0131 ele alaca\u011f\u0131z.<\/p>\n<div class=\"tip\">\n        Uzman \u0130pucu: Makro geni\u015flemesini g\u00f6rmek i\u00e7in derleyicinizin <code class=\"language-bash\">-E<\/code> bayra\u011f\u0131n\u0131 kullan\u0131n (\u00f6rne\u011fin <code class=\"language-bash\">gcc -E main.c -o main.i<\/code>). Bu, \u00f6ni\u015flemcinin makrolar\u0131 nas\u0131l i\u015fledi\u011fini anlaman\u0131za ve hatalar\u0131 ay\u0131klaman\u0131za yard\u0131mc\u0131 olur.\n    <\/div>\n<h3>Performans Etkileri ve Makro Geni\u015fletmesi<\/h3>\n<p>\u00d6ni\u015flemci makrolar\u0131, derleme zaman\u0131nda metinsel yer de\u011fi\u015ftirmeler yapt\u0131\u011f\u0131 i\u00e7in \u00e7al\u0131\u015fma zaman\u0131 performans\u0131na do\u011frudan bir etkisi yoktur. Makrolar, derleyici kodu g\u00f6rmeden \u00f6nce geni\u015fletilir ve nihai kod derlenir. Bu, makrolar\u0131n, k\u00fc\u00e7\u00fck fonksiyonlar i\u00e7in bazen bir ba\u015far\u0131m maliyeti olabilen fonksiyon \u00e7a\u011fr\u0131s\u0131 y\u00fck\u00fcn\u00fc (overhead) ortadan kald\u0131rd\u0131\u011f\u0131 anlam\u0131na gelir. Ancak, \u00e7ok b\u00fcy\u00fck makrolar\u0131n geni\u015flemesi, derleme s\u00fcresini uzatabilir ve \u00fcretilen ikili dosyan\u0131n boyutunu art\u0131rabilir. Genellikle bu, \u00e7o\u011fu uygulama i\u00e7in g\u00f6z ard\u0131 edilebilir bir durumdur.<\/p>\n<h3>Hata Ay\u0131klama Zorluklar\u0131 ve \u00c7\u00f6z\u00fcmler<\/h3>\n<p>Karma\u015f\u0131k makrolar\u0131n en b\u00fcy\u00fck dezavantajlar\u0131ndan biri, hata ay\u0131klaman\u0131n zorlu\u011fudur. Makrolar genellikle bir ifade gibi g\u00f6r\u00fcnse de, asl\u0131nda geni\u015fletildi\u011finde \u00e7ok farkl\u0131 bir kod par\u00e7as\u0131na d\u00f6n\u00fc\u015febilir. Bu, hata mesajlar\u0131n\u0131n veya bir hata ay\u0131klay\u0131c\u0131daki ad\u0131m ad\u0131m \u00e7al\u0131\u015ft\u0131rman\u0131n yan\u0131lt\u0131c\u0131 olmas\u0131na neden olabilir. \u00c7\u00f6z\u00fcm olarak:<\/p>\n<ul>\n<li><strong>Derleyici Bayraklar\u0131:<\/strong> GCC ve Clang gibi derleyiciler, <code class=\"language-bash\">-E<\/code> (sadece \u00f6ni\u015fleme) veya <code class=\"language-bash\">-fdump-macros<\/code> gibi bayraklar sunarak makro geni\u015flemesini g\u00f6rmemizi sa\u011flar.<\/li>\n<li><strong>K\u00fc\u00e7\u00fck ve Odakl\u0131 Makrolar:<\/strong> Karma\u015f\u0131k g\u00f6revleri tek bir dev makro yerine, daha k\u00fc\u00e7\u00fck, tek bir i\u015flevi yerine getiren makrolara ay\u0131r\u0131n.<\/li>\n<li><strong><code class=\"language-c\">do { ... } while(0)<\/code> \u0130fadesi:<\/strong> Makrolar\u0131 bloklar halinde sarmak (\u00f6zellikle \u00e7ok sat\u0131rl\u0131 makrolar i\u00e7in), noktal\u0131 virg\u00fcl sorunlar\u0131n\u0131 ve <code class=\"language-c\">if\/else<\/code> ifadelerindeki beklenmedik davran\u0131\u015flar\u0131 \u00f6nler.<\/li>\n<\/ul>\n<h3>Makro G\u00fcvenli\u011fi ve Yan Etkiler<\/h3>\n<p>Makrolar, arg\u00fcmanlar\u0131 do\u011frudan metinsel olarak de\u011fi\u015ftirdi\u011fi i\u00e7in beklenmedik yan etkilere yol a\u00e7abilir. \u00d6rne\u011fin, bir makro arg\u00fcman\u0131n\u0131 birden fazla kez de\u011ferlendirirse, yan etkili ifadeler (\u00f6rne\u011fin <code class=\"language-c\">i++<\/code>) birden fazla kez \u00e7al\u0131\u015fabilir. Bunu \u00f6nlemek i\u00e7in:<\/p>\n<ul>\n<li><strong>Arg\u00fcmanlar\u0131 Parantez \u0130\u00e7ine Al\u0131n:<\/strong> Makro arg\u00fcmanlar\u0131n\u0131 kullan\u0131rken daima parantez i\u00e7ine al\u0131n. \u00d6rne\u011fin, <code class=\"language-c\">#define KARE(x) ((x)*(x))<\/code> yerine <code class=\"language-c\">#define KARE(x) x*x<\/code> yazmak, <code class=\"language-c\">KARE(a+b)<\/code> gibi durumlarda hatal\u0131 geni\u015flemeye yol a\u00e7ar.<\/li>\n<li><strong>Yan Etkili \u0130fadelerden Ka\u00e7\u0131n\u0131n:<\/strong> M\u00fcmk\u00fcnse makrolara yan etkili ifadeler ge\u00e7irmeyin. E\u011fer ka\u00e7\u0131n\u0131lmazsa, <code class=\"language-c\">({ ... })<\/code> gibi GNU uzant\u0131s\u0131 blok ifadeleri veya ge\u00e7ici de\u011fi\u015fkenler kullanarak de\u011ferlendirmenin sadece bir kez yap\u0131lmas\u0131n\u0131 sa\u011flay\u0131n.<\/li>\n<\/ul>\n<h3>C++'da Alternatifler<\/h3>\n<p>E\u011fer C++ ortam\u0131nda \u00e7al\u0131\u015f\u0131yorsan\u0131z, bir\u00e7ok makro kullan\u0131m durumu i\u00e7in daha g\u00fcvenli ve modern alternatifler mevcuttur:<\/p>\n<ul>\n<li><strong><code class=\"language-cpp\">inline<\/code> Fonksiyonlar:<\/strong> Performans a\u00e7\u0131s\u0131ndan makrolara benzer, ancak t\u00fcr g\u00fcvenli\u011fi ve normal fonksiyon s\u00f6zdizimi sunar.<\/li>\n<li><strong>\u015eablon Fonksiyonlar\u0131 (<code class=\"language-cpp\">template<\/code> functions):<\/strong> Genel t\u00fcrler \u00fczerinde \u00e7al\u0131\u015fabilen ve g\u00fc\u00e7l\u00fc t\u00fcr g\u00fcvenli\u011fi sa\u011flayan esnek fonksiyonlar olu\u015fturman\u0131za olanak tan\u0131r. \u00d6zellikle variadic template'ler, de\u011fi\u015fken say\u0131da arg\u00fcman\u0131 \u00e7ok daha g\u00fcvenli ve okunabilir bir \u015fekilde ele al\u0131r.<\/li>\n<li><strong>Fonksiyon A\u015f\u0131r\u0131 Y\u00fcklemesi (<code class=\"language-cpp\">function overloading<\/code>):<\/strong> Farkl\u0131 arg\u00fcman listeleriyle ayn\u0131 isme sahip birden \u00e7ok fonksiyon tan\u0131mlayarak, makro a\u015f\u0131r\u0131 y\u00fckleme mant\u0131\u011f\u0131n\u0131 daha temiz bir \u015fekilde uygulayabilirsiniz.<\/li>\n<\/ul>\n<p>Bu ileri d\u00fczey ipu\u00e7lar\u0131, makrolar\u0131 daha verimli ve g\u00fcvenli bir \u015fekilde kullanman\u0131za yard\u0131mc\u0131 olacakt\u0131r. Ancak unutmay\u0131n, her ara\u00e7 gibi makrolar\u0131n da en iyi kullan\u0131ld\u0131\u011f\u0131 belirli durumlar ve ka\u00e7\u0131n\u0131lmas\u0131 gereken tuzaklar vard\u0131r.<\/p>\n<h2>Sonu\u00e7: C23 \u00d6ncesi Makro D\u00fcnyas\u0131nda Esneklik ve Kontrol<\/h2>\n<p><code class=\"language-c\">__VA_OPT__<\/code>, modern C ve C++ standartlar\u0131n\u0131n sundu\u011fu, variadic makrolar\u0131 daha esnek ve hatas\u0131z hale getiren harika bir \u00f6zelliktir. Ancak, bu \u00f6zelli\u011fin bulunmad\u0131\u011f\u0131 eski derleyiciler veya standartlar ile \u00e7al\u0131\u015f\u0131rken, geli\u015ftiricilerin eli kolu ba\u011fl\u0131 de\u011fildir. G\u00f6rd\u00fc\u011f\u00fcm\u00fcz gibi, geli\u015fmi\u015f C \u00f6ni\u015flemci makro teknikleri sayesinde, arg\u00fcman sayma, makro a\u015f\u0131r\u0131 y\u00fckleme ve derleyiciye \u00f6zel uzant\u0131lar gibi y\u00f6ntemlerle <code class=\"language-c\">__VA_OPT__<\/code>'un sa\u011flad\u0131\u011f\u0131 esnekli\u011fi taklit etmek m\u00fcmk\u00fcnd\u00fcr. \u00d6zellikle arg\u00fcman sayma ve buna g\u00f6re farkl\u0131 uygulama makrolar\u0131na y\u00f6nlendirme, en ta\u015f\u0131nabilir ve standartlara uygun \u00e7\u00f6z\u00fcm\u00fc sunar.<\/p>\n<p>Bu teknikleri kullanarak, hem karma\u015f\u0131k loglama sistemleri hem de dinamik hata ay\u0131klama (<code class=\"language-c\">assert<\/code>) mekanizmalar\u0131 olu\u015fturarak kodumuzun kalitesini ve s\u00fcrd\u00fcr\u00fclebilirli\u011fini art\u0131rabiliriz. Elbette, bu ileri d\u00fczey makro \"sihirbazl\u0131\u011f\u0131\" beraberinde baz\u0131 karma\u015f\u0131kl\u0131klar\u0131 ve hata ay\u0131klama zorluklar\u0131n\u0131 getirebilir. Bu y\u00fczden, kod okunabilirli\u011finden \u00f6d\u00fcn vermemek, makro g\u00fcvenli\u011fine dikkat etmek ve m\u00fcmk\u00fcn oldu\u011funda C++'daki <code class=\"language-cpp\">inline<\/code> fonksiyonlar veya variadic template'ler gibi daha modern ve t\u00fcr g\u00fcvenli alternatifleri de\u011ferlendirmek \u00f6nemlidir. Neticede, hangi y\u00f6ntemi se\u00e7erseniz se\u00e7in, temel ama\u00e7, kodunuza esneklik ve kontrol katarken, onu anla\u015f\u0131l\u0131r ve y\u00f6netilebilir tutmakt\u0131r.<\/p>\n<h3>S\u0131k\u00e7a Sorulan Sorular (SSS)<\/h3>\n<p><strong>1. Bu teknikler C++ kodunda da kullan\u0131labilir mi?<\/strong><\/p>\n<p>Evet, bu makalede bahsedilen C \u00f6ni\u015flemci makro tekniklerinin tamam\u0131 C++ kodunda da kullan\u0131labilir. C++ \u00f6ni\u015flemcisi, C \u00f6ni\u015flemcisinin superset'idir ve ayn\u0131 kurallar\u0131 takip eder. Ancak C++'da <code class=\"language-cpp\">inline<\/code> fonksiyonlar, \u015fablonlar (\u00f6zellikle variadic template'ler) ve fonksiyon a\u015f\u0131r\u0131 y\u00fcklemesi gibi daha modern ve t\u00fcr g\u00fcvenli alternatifler genellikle tercih edilir.<\/p>\n<p><strong>2. <code class=\"language-c\">__VA_OPT__<\/code> yerine bu karma\u015f\u0131k makrolar\u0131 kullanmak ne gibi dezavantajlar getirir?<\/strong><\/p>\n<p>Temel dezavantajlar aras\u0131nda kod karma\u015f\u0131kl\u0131\u011f\u0131, okunabilirli\u011fin azalmas\u0131, hata ay\u0131klaman\u0131n zorla\u015fmas\u0131 ve ta\u015f\u0131nabilirli\u011fin baz\u0131 durumlarda (derleyici uzant\u0131lar\u0131 kullan\u0131ld\u0131\u011f\u0131nda) k\u0131s\u0131tlanmas\u0131 yer al\u0131r. <code class=\"language-c\">__VA_OPT__<\/code>'un aksine, bu teknikler genellikle daha fazla yard\u0131mc\u0131 makro tan\u0131m\u0131 gerektirir ve hataya a\u00e7\u0131k olabilir.<\/p>\n<p><strong>3. Performans \u00fczerinde herhangi bir etkisi var m\u0131?<\/strong><\/p>\n<p>Hay\u0131r, \u00f6ni\u015flemci makrolar\u0131 derleme zaman\u0131nda geni\u015fletildi\u011fi i\u00e7in \u00e7al\u0131\u015fma zaman\u0131 performans\u0131na do\u011frudan bir etkisi yoktur. T\u00fcm geni\u015fletmeler derleyiciye kod ula\u015fmadan \u00f6nce tamamlan\u0131r. Ancak \u00e7ok b\u00fcy\u00fck makrolar\u0131n geni\u015fletilmesi derleme s\u00fcresini bir miktar uzatabilir.<\/p>\n<p><strong>4. Hangi derleyiciler <code class=\"language-c\"><strong>__VA_ARGS__<\/code> uzant\u0131s\u0131n\u0131 destekler?<\/strong><\/p>\n<p><\/strong><\/p>\n<p><code class=\"language-c\"><strong>__VA_ARGS__<\/code> uzant\u0131s\u0131, GNU C\/C++ derleyicisi (GCC) ve Clang gibi GNU uyumlu derleyiciler taraf\u0131ndan desteklenir. Microsoft Visual C++ (MSVC) gibi di\u011fer derleyiciler genellikle bu uzant\u0131y\u0131 desteklemez ve bu durumda ta\u015f\u0131nabilir arg\u00fcman sayma yakla\u015f\u0131mlar\u0131na ba\u015fvurmak gerekir.<\/p>\n<p><\/strong><\/p>\n<p><strong>5. Daha modern C++ s\u00fcr\u00fcmlerinde (C++20 ve sonras\u0131) benzer sorunlar var m\u0131?<\/strong><\/p>\n<p>Hay\u0131r, C++20 standard\u0131 ile <code class=\"language-c\">__VA_OPT__<\/code> \u00f6zelli\u011fi tan\u0131t\u0131lm\u0131\u015ft\u0131r ve bu, \u00f6nceki variadic makro sorununu do\u011frudan \u00e7\u00f6zer. Bu nedenle, C++20 veya daha yeni bir standartta derleme yapabiliyorsan\u0131z, bu karma\u015f\u0131k makro hilelerine genellikle ihtiyac\u0131n\u0131z kalmaz ve do\u011frudan <code class=\"language-c\">__VA_OPT__<\/code>'u kullanabilirsiniz.<\/p>\n<p><\/body><\/p>\n","protected":false},"excerpt":{"rendered":"C ve C++ programlamas\u0131nda, esnek ve yeniden kullan\u0131labilir kod bloklar\u0131 olu\u015fturmak i\u00e7in \u00f6ni\u015flemci makrolar\u0131 vazge\u00e7ilmez ara\u00e7lard\u0131r. Ancak, de\u011fi\u015fken&hellip;","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1],"tags":[],"class_list":{"0":"post-34518","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-genel","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>C23 \u00d6ncesi `__VA_OPT__` Alternatifi: Geli\u015fmi\u015f C Makrolar\u0131<\/title>\n<meta name=\"description\" content=\"C ve C++ programlamas\u0131nda, esnek ve yeniden kullan\u0131labilir kod bloklar\u0131 olu\u015fturmak i\u00e7in \u00f6ni\u015flemci makrolar\u0131 vazge\u00e7ilmez ara\u00e7lard\u0131r. Ancak, de\u011fi\u015fken say\u0131da arg\u00fcman alan (variadic) makrolarla \u00e7al\u0131\u015f\u0131rken, \u00f6zellikle bu arg\u00fcmanlar\u0131n iste\u011fe ba\u011fl\u0131 oldu\u011fu durumlarda, klasik yakla\u015f\u0131mlar belirli zorluklar \u00e7\u0131kar\u0131r. C23 ve C++20 standartlar\u0131 ile gelen __VA_OPT__ makrosu bu sorunu zarif\u00e7e \u00e7\u00f6zse de, daha eski derleyiciler ve standartlarla \u00e7al\u0131\u015fmak zorunda kalan geli\u015ftiriciler i\u00e7in bu \u00f6zellik bir l\u00fckst\u00fcr. Peki, __VA_OPT__ olmadan, iste\u011fe ba\u011fl\u0131 makro arg\u00fcmanlar\u0131n\u0131 temiz ve hatas\u0131z bir \u015fekilde nas\u0131l y\u00f6netebiliriz? Bu makale, tam da bu soruya odaklanarak, geli\u015fmi\u015f C \u00f6ni\u015flemci makrolar\u0131 kullanarak bu eksikli\u011fi gidermenin yollar\u0131n\u0131 ad\u0131m ad\u0131m a\u00e7\u0131klayacak ve ger\u00e7ek d\u00fcnya senaryolar\u0131yla destekleyecektir. Eski sistemlerde dahi modern esnekli\u011fi yakalamak isteyenler i\u00e7in kapsaml\u0131 bir rehber niteli\u011findedir.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"C23 \u00d6ncesi `__VA_OPT__` Alternatifi: Geli\u015fmi\u015f C Makrolar\u0131\" \/>\n<meta property=\"og:description\" content=\"C ve C++ programlamas\u0131nda, esnek ve yeniden kullan\u0131labilir kod bloklar\u0131 olu\u015fturmak i\u00e7in \u00f6ni\u015flemci makrolar\u0131 vazge\u00e7ilmez ara\u00e7lard\u0131r. Ancak, de\u011fi\u015fken say\u0131da arg\u00fcman alan (variadic) makrolarla \u00e7al\u0131\u015f\u0131rken, \u00f6zellikle bu arg\u00fcmanlar\u0131n iste\u011fe ba\u011fl\u0131 oldu\u011fu durumlarda, klasik yakla\u015f\u0131mlar belirli zorluklar \u00e7\u0131kar\u0131r. C23 ve C++20 standartlar\u0131 ile gelen __VA_OPT__ makrosu bu sorunu zarif\u00e7e \u00e7\u00f6zse de, daha eski derleyiciler ve standartlarla \u00e7al\u0131\u015fmak zorunda kalan geli\u015ftiriciler i\u00e7in bu \u00f6zellik bir l\u00fckst\u00fcr. Peki, __VA_OPT__ olmadan, iste\u011fe ba\u011fl\u0131 makro arg\u00fcmanlar\u0131n\u0131 temiz ve hatas\u0131z bir \u015fekilde nas\u0131l y\u00f6netebiliriz? Bu makale, tam da bu soruya odaklanarak, geli\u015fmi\u015f C \u00f6ni\u015flemci makrolar\u0131 kullanarak bu eksikli\u011fi gidermenin yollar\u0131n\u0131 ad\u0131m ad\u0131m a\u00e7\u0131klayacak ve ger\u00e7ek d\u00fcnya senaryolar\u0131yla destekleyecektir. Eski sistemlerde dahi modern esnekli\u011fi yakalamak isteyenler i\u00e7in kapsaml\u0131 bir rehber niteli\u011findedir.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-18T01:31:38+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"25 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"C23 \u00d6ncesi `__VA_OPT__` Alternatifi: Geli\u015fmi\u015f C Makrolar\u0131\",\"datePublished\":\"2025-11-18T01:31:38+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/\"},\"wordCount\":3025,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/#respond\"]}],\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/\",\"name\":\"C23 \u00d6ncesi `__VA_OPT__` Alternatifi: Geli\u015fmi\u015f C Makrolar\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2025-11-18T01:31:38+00:00\",\"description\":\"C ve C++ programlamas\u0131nda, esnek ve yeniden kullan\u0131labilir kod bloklar\u0131 olu\u015fturmak i\u00e7in \u00f6ni\u015flemci makrolar\u0131 vazge\u00e7ilmez ara\u00e7lard\u0131r. Ancak, de\u011fi\u015fken say\u0131da arg\u00fcman alan (variadic) makrolarla \u00e7al\u0131\u015f\u0131rken, \u00f6zellikle bu arg\u00fcmanlar\u0131n iste\u011fe ba\u011fl\u0131 oldu\u011fu durumlarda, klasik yakla\u015f\u0131mlar belirli zorluklar \u00e7\u0131kar\u0131r. C23 ve C++20 standartlar\u0131 ile gelen __VA_OPT__ makrosu bu sorunu zarif\u00e7e \u00e7\u00f6zse de, daha eski derleyiciler ve standartlarla \u00e7al\u0131\u015fmak zorunda kalan geli\u015ftiriciler i\u00e7in bu \u00f6zellik bir l\u00fckst\u00fcr. Peki, __VA_OPT__ olmadan, iste\u011fe ba\u011fl\u0131 makro arg\u00fcmanlar\u0131n\u0131 temiz ve hatas\u0131z bir \u015fekilde nas\u0131l y\u00f6netebiliriz? Bu makale, tam da bu soruya odaklanarak, geli\u015fmi\u015f C \u00f6ni\u015flemci makrolar\u0131 kullanarak bu eksikli\u011fi gidermenin yollar\u0131n\u0131 ad\u0131m ad\u0131m a\u00e7\u0131klayacak ve ger\u00e7ek d\u00fcnya senaryolar\u0131yla destekleyecektir. Eski sistemlerde dahi modern esnekli\u011fi yakalamak isteyenler i\u00e7in kapsaml\u0131 bir rehber niteli\u011findedir.\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"C23 \u00d6ncesi `__VA_OPT__` Alternatifi: Geli\u015fmi\u015f C Makrolar\u0131\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"C23 \u00d6ncesi `__VA_OPT__` Alternatifi: Geli\u015fmi\u015f C Makrolar\u0131","description":"C ve C++ programlamas\u0131nda, esnek ve yeniden kullan\u0131labilir kod bloklar\u0131 olu\u015fturmak i\u00e7in \u00f6ni\u015flemci makrolar\u0131 vazge\u00e7ilmez ara\u00e7lard\u0131r. Ancak, de\u011fi\u015fken say\u0131da arg\u00fcman alan (variadic) makrolarla \u00e7al\u0131\u015f\u0131rken, \u00f6zellikle bu arg\u00fcmanlar\u0131n iste\u011fe ba\u011fl\u0131 oldu\u011fu durumlarda, klasik yakla\u015f\u0131mlar belirli zorluklar \u00e7\u0131kar\u0131r. C23 ve C++20 standartlar\u0131 ile gelen __VA_OPT__ makrosu bu sorunu zarif\u00e7e \u00e7\u00f6zse de, daha eski derleyiciler ve standartlarla \u00e7al\u0131\u015fmak zorunda kalan geli\u015ftiriciler i\u00e7in bu \u00f6zellik bir l\u00fckst\u00fcr. Peki, __VA_OPT__ olmadan, iste\u011fe ba\u011fl\u0131 makro arg\u00fcmanlar\u0131n\u0131 temiz ve hatas\u0131z bir \u015fekilde nas\u0131l y\u00f6netebiliriz? Bu makale, tam da bu soruya odaklanarak, geli\u015fmi\u015f C \u00f6ni\u015flemci makrolar\u0131 kullanarak bu eksikli\u011fi gidermenin yollar\u0131n\u0131 ad\u0131m ad\u0131m a\u00e7\u0131klayacak ve ger\u00e7ek d\u00fcnya senaryolar\u0131yla destekleyecektir. Eski sistemlerde dahi modern esnekli\u011fi yakalamak isteyenler i\u00e7in kapsaml\u0131 bir rehber niteli\u011findedir.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/","og_locale":"tr_TR","og_type":"article","og_title":"C23 \u00d6ncesi `__VA_OPT__` Alternatifi: Geli\u015fmi\u015f C Makrolar\u0131","og_description":"C ve C++ programlamas\u0131nda, esnek ve yeniden kullan\u0131labilir kod bloklar\u0131 olu\u015fturmak i\u00e7in \u00f6ni\u015flemci makrolar\u0131 vazge\u00e7ilmez ara\u00e7lard\u0131r. Ancak, de\u011fi\u015fken say\u0131da arg\u00fcman alan (variadic) makrolarla \u00e7al\u0131\u015f\u0131rken, \u00f6zellikle bu arg\u00fcmanlar\u0131n iste\u011fe ba\u011fl\u0131 oldu\u011fu durumlarda, klasik yakla\u015f\u0131mlar belirli zorluklar \u00e7\u0131kar\u0131r. C23 ve C++20 standartlar\u0131 ile gelen __VA_OPT__ makrosu bu sorunu zarif\u00e7e \u00e7\u00f6zse de, daha eski derleyiciler ve standartlarla \u00e7al\u0131\u015fmak zorunda kalan geli\u015ftiriciler i\u00e7in bu \u00f6zellik bir l\u00fckst\u00fcr. Peki, __VA_OPT__ olmadan, iste\u011fe ba\u011fl\u0131 makro arg\u00fcmanlar\u0131n\u0131 temiz ve hatas\u0131z bir \u015fekilde nas\u0131l y\u00f6netebiliriz? Bu makale, tam da bu soruya odaklanarak, geli\u015fmi\u015f C \u00f6ni\u015flemci makrolar\u0131 kullanarak bu eksikli\u011fi gidermenin yollar\u0131n\u0131 ad\u0131m ad\u0131m a\u00e7\u0131klayacak ve ger\u00e7ek d\u00fcnya senaryolar\u0131yla destekleyecektir. Eski sistemlerde dahi modern esnekli\u011fi yakalamak isteyenler i\u00e7in kapsaml\u0131 bir rehber niteli\u011findedir.","og_url":"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2025-11-18T01:31:38+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"25 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"C23 \u00d6ncesi `__VA_OPT__` Alternatifi: Geli\u015fmi\u015f C Makrolar\u0131","datePublished":"2025-11-18T01:31:38+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/"},"wordCount":3025,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/#respond"]}],"copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/","url":"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/","name":"C23 \u00d6ncesi `__VA_OPT__` Alternatifi: Geli\u015fmi\u015f C Makrolar\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2025-11-18T01:31:38+00:00","description":"C ve C++ programlamas\u0131nda, esnek ve yeniden kullan\u0131labilir kod bloklar\u0131 olu\u015fturmak i\u00e7in \u00f6ni\u015flemci makrolar\u0131 vazge\u00e7ilmez ara\u00e7lard\u0131r. Ancak, de\u011fi\u015fken say\u0131da arg\u00fcman alan (variadic) makrolarla \u00e7al\u0131\u015f\u0131rken, \u00f6zellikle bu arg\u00fcmanlar\u0131n iste\u011fe ba\u011fl\u0131 oldu\u011fu durumlarda, klasik yakla\u015f\u0131mlar belirli zorluklar \u00e7\u0131kar\u0131r. C23 ve C++20 standartlar\u0131 ile gelen __VA_OPT__ makrosu bu sorunu zarif\u00e7e \u00e7\u00f6zse de, daha eski derleyiciler ve standartlarla \u00e7al\u0131\u015fmak zorunda kalan geli\u015ftiriciler i\u00e7in bu \u00f6zellik bir l\u00fckst\u00fcr. Peki, __VA_OPT__ olmadan, iste\u011fe ba\u011fl\u0131 makro arg\u00fcmanlar\u0131n\u0131 temiz ve hatas\u0131z bir \u015fekilde nas\u0131l y\u00f6netebiliriz? Bu makale, tam da bu soruya odaklanarak, geli\u015fmi\u015f C \u00f6ni\u015flemci makrolar\u0131 kullanarak bu eksikli\u011fi gidermenin yollar\u0131n\u0131 ad\u0131m ad\u0131m a\u00e7\u0131klayacak ve ger\u00e7ek d\u00fcnya senaryolar\u0131yla destekleyecektir. Eski sistemlerde dahi modern esnekli\u011fi yakalamak isteyenler i\u00e7in kapsaml\u0131 bir rehber niteli\u011findedir.","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/c23-oncesi-__va_opt__-alternatifi-gelismis-c-makrolari\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"C23 \u00d6ncesi `__VA_OPT__` Alternatifi: Geli\u015fmi\u015f C Makrolar\u0131"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34518","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=34518"}],"version-history":[{"count":0,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34518\/revisions"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=34518"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=34518"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=34518"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}