Skip to content
2025.11.07.
  • F
  • X
  • LinkedIn
  • YouTube
  • Instagram
  • GitHub
TavIR

TavIR

Mikrokontroller világ

  • TavIR Tudástár
  • TavIR WebShop
  • TavIR Fórum
  • Hírek
  • Könyvek
    • Egyszerű elektronika – Kezdőlap
    • ESP8266/ESP32
    • Tippek
      • Tippek-trükkök (AVR)
      • Tippek-trükkök (ESP8266/ESP32)
  • +Gyorstippek
  • +Mélyvíz
  • +Témakereső
  • Kapcsolat
  • Főoldal
  • Cikk
  • Rejtett szimbólumok az Arduino kódban, avagy mit ad hozzá a fordító? – A fordítási makrók világa
  • Cikk
  • Mélyvíz
  • Tippek

Rejtett szimbólumok az Arduino kódban, avagy mit ad hozzá a fordító? – A fordítási makrók világa

Robert 2025.05.25.
Egy laptop képernyőjén Arduino C-kód látható, miközben körülötte különböző mikrovezérlő panelek és szenzorok vannak elhelyezve egy műhelyasztalon.

Nem minden sor a saját kezünkből származik – van, amit a fordító ad hozzá. Az Arduino mögött dolgozó fordító önállóan kiegészíti a programot olyan sorokkal, olyan szimbólumokat, mint __DATE__, F_CPU vagy ARDUINO_AVR_UNO, amiket te sosem írtál le, mégis ott vannak. Ezek a rejtett, előfeldolgozási szimbólumok irányítják, mit hogyan fordít le a rendszer – és néha többet mondanak el a programodról, mint maga a kód.

Tartalomjegyzék

Toggle
  • A beépített szimbólumok világa
    • Láthatatlan sorok, amiket nem te írtál
    • Neve van, de nem változó
    • Háromféle helyről származhatnak
  • Hasznos és gyakori szimbólumok – példákkal és háttérrel
    • Idő és fájlinformációk – amikor a kód elmondja, mikor született
    • Fordítói környezet – amikor a programkód kérdezi, ki fordítja
    • Mikrokontroller típus és architektúra – célhardver felismerése
  • Az Arduino környezet által definiált szimbólumok
    • IDE-verzió, architektúra és alaplap-változat – a platform nyomai
    • Órajel (F_CPU) – a rejtett időzítő
    • USB és hardver-specifikus azonosítók
    • Könyvtárbeállítások és IDE-fázis szimbólumok
  • Hol és hogyan találhatók meg ezek a szimbólumok?
    • Láthatatlan, de nem elérhetetlen – a makrók felfedése
    • 1. Kódon belüli ellenőrzés – fejlesztői trükkök
    • 2. IDE és buildrendszer: honnan jönnek ezek?
    • Javasolt fejlesztési gyakorlat
  • Mire jó mindez?
    • Hibakeresés, naplózás, visszajátszható kódverziók
    • Testreszabott kód különböző hardverekre
    • Platform- és verzióspecifikus optimalizálás
    • Automatikus dokumentáció – a firmware saját magát azonosítja
    • Feltételes hibakezelés és biztonságosabb build
    • Hatékony kód újrafelhasználás – egyetlen forrás, sok célra
  • Kitekintés – a preproceszor határai és öröksége
    • Történeti háttér – honnan jött a preproceszor?
    • Hogyan működik pontosan a preproceszor?
    • A metaprogramozás határán
    • Más nyelvek hogyan oldják meg?
    • Hol a határ? Mikor NE használjuk?
  • A nagy mintakód
    • Beépített makrók feltérképezése – amit az IDE elhallgat
  • Zárás – Neked van kedvenc szimbólumod?
    • Te mit gondolsz?

A beépített szimbólumok világa

Láthatatlan sorok, amiket nem te írtál

Amikor egy Arduino programot (vagyis sketch-et) fordítasz, valójában nem csak azt a néhány tucat sort dolgozza fel a rendszer, amit te gépeltél be. A háttérben a fordító – és vele együtt az előfeldolgozó modul – számos kiegészítést végez a forráskódon: automatikusan kiegészíti a forráskódot különféle rejtett segédelemekkel – ezek az Arduino beépített fordítási szimbólumok használata révén működő beépített szimbólumok.

Ezek olyan kulcsszavak, változónak tűnő azonosítók, amelyeket nem látsz, mégis ott vannak. Fordítási időben léteznek, és segítik a program optimalizálását, platformhoz igazítását, hibakeresését. Mintha a rendszer suttyomban belekotyogna a kódodba – jóindulatúan, de határozottan.

Neve van, de nem változó

A programozásban nem minden az, aminek elsőre látszik. Például:

  • A F_CPU nem változó – hanem makró (macro), amit a fordítás előtt a preproceszor automatikusan behelyettesít egy számszerű értékre (pl. 16000000UL).
  • A __LINE__ nem egy függvény – hanem egy beépített szimbólum (predefined macro), amit a fordító az aktuális sor számmal helyettesít.
  • A __AVR_ATmega328P__ egy fordító által előállított azonosító (compiler-defined macro), ami csak akkor létezik, ha tényleg ATmega328P célhardverre fordítunk.

Ezek nem futásidőben működnek. A mikrokontrollerben nem tárolódnak el. Ezek a nyelv és a fordítórendszer rejtett vezényszavai.

Mikrokontrolleres áramkör előtt lebegő programkód modern irodai háttérrel. Arduino fordító utasításokkal.
Kód és vezérlés: a digitális rendszerek szíve.

Háromféle helyről származhatnak

1. A nyelv alapból tudja – ez a C/C++ ajándéka

Ezek a szimbólumok minden szabványos C vagy C++ fordító részei. Bárhol is írsz C-kódot – legyen az Linuxon, egy ESP32-n vagy egy UNO-n – ezek működni fognak:

  • __FILE__ – A forrásfájl neve, idézőjelben
  • __LINE__ – A kódsor sorszáma
  • __DATE__ – A fordítás napja
  • __TIME__ – A fordítás ideje
  • __STDC__ – Azt jelzi, hogy szabványos C-t használunk
  • __cplusplus – Megmondja, hogy C++ nyelven fordítunk-e

2. A fordító tesz hozzá – például az avr-gcc

A GCC-alapú fordítók – például amit az Arduino is használ AVR-hez – különféle saját makrókat adnak hozzá. Ezek már nem minden platformon elérhetők, de ha például ATmega328P-re fordítasz, akkor:

  • __AVR__ – Jelzi, hogy AVR architektúrára fordítunk
  • __AVR_ARCH__ – Megadja az architektúra számkódját
  • __AVR_ATmega328P__ – Csak akkor van jelen, ha a cél ATmega328P
  • __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__ – A GCC verzióját mutatják

Külön kis érdekesség a __has_include(x) – ezzel megkérdezheted, hogy egy adott fejlécfájl elérhető-e. Olyasmi, mint egy könyvtárosi súgó: „Van ilyen könyved?” – „Nincs, sajnálom, lapozz tovább.”

3. Az Arduino is beleszól – IDE-függő szimbólumok

Az Arduino IDE sem tétlen a háttérben. Amikor kiválasztod, hogy UNO-t használsz, a rendszer beír a háttérbe olyan szimbólumokat, mint:

  • ARDUINO – A használt IDE verziója (pl. 10819 = 1.8.19)
  • ARDUINO_AVR_UNO – Az alaplap típusa
  • ARDUINO_ARCH_AVR – Az architektúra neve
  • F_CPU – A processzor órajele hertzben, pl. 16000000UL
  • USB_VID, USB_PID – USB azonosítók, ha releváns
  • ARDUINO_LIB_DISCOVERY_PHASE, ARDUINO_USB_MODE – Speciális szimbólumok a könyvtárkezelőhöz

Ezeket a rendszer automatikusan biztosítja, nem szükséges külön definiálni őket. De jó ha tudod, hogy léteznek.

Hasznos és gyakori szimbólumok – példákkal és háttérrel

Idő és fájlinformációk – amikor a kód elmondja, mikor született

Ezek a szimbólumok nem a futás közbeni működést, hanem a fordítás pillanatát tükrözik. A legtöbbjük az ISO C szabvány része, és gyakorlatilag minden platformon elérhető.

SzimbólumFordító adja?Érték típusaMire jó?
__DATE__Igen"Mmm dd yyyy" stringBuild időbélyeg
__TIME__Igen"hh:mm:ss" stringDebug timestamp
__FILE__Igen"filename.ext"Forrásfájl azonosítása
__LINE__IgenEgész számKódsor követése, naplózás

Miért fontos?

  • Hibakeresés során ki tudjuk írni, pontosan mikor fordult a program.
  • Naplózásban feltüntethetjük, melyik fájl melyik sora futott – ez különösen akkor hasznos, ha több forrásmodulból épül a projekt.

Példa: debug log kód helyének kiírására

1
2
3
4
5
6
#define DEBUG_LOG(msg) Serial.print("["); Serial.print(__FILE__); Serial.print(":"); Serial.print(__LINE__); Serial.print("] "); Serial.println(msg);
 
void setup() {
  Serial.begin(9600);
  DEBUG_LOG("Program indul");
}

Eredmény:
[main.ino:5] Program indul

Ez a technika már-már mini hibaútvonal-detektorként is szolgálhat egyszerűbb projekteknél.

Kis képernyős eszköz jelenít meg firmware-információkat egy forrasztópáka és jegyzetfüzet mellett.
Beágyazott világ: firmware a gyakorlatban.

Fordítói környezet – amikor a programkód kérdezi, ki fordítja

Itt nem csak arról van szó, hogy GCC-t használunk-e. Ezek a szimbólumok segítenek megállapítani, milyen verziójú GCC dolgozik, vagy hogy éppen C vagy C++ nyelvet használunk.

SzimbólumTípusPéldaMire jó?
__GNUC__Compiler macro5GCC főverzió felismerés
__GNUC_MINOR__Compiler macro4GCC alverzió felismerés
__GNUC_PATCHLEVEL__Compiler macro0GCC patch szintje
__cplusplusLanguage macro199711L vagy 201103LJelzi, hogy C++-t fordítunk

Mire jó ez?

  • A programkód alkalmazkodhat ahhoz, hogy milyen fordítóverzió fut.
  • Könyvtárak írásánál vagy platformfüggetlen kódnál elengedhetetlen.

Példa – fordító verzió szerinti logika:

1
2
3
4
5
6
#if __GNUC__ >= 5
  Serial.println("Modern GCC fordító");
#else
  Serial.println("Régebbi GCC verzió");
#endif
 

Mikrokontroller típus és architektúra – célhardver felismerése

Ez az egyik legfontosabb terület, ha többféle Arduino lapot szeretnénk támogatni ugyanazzal a kóddal. Az alábbi makrókat az AVR-GCC fordító állítja be automatikusan a kiválasztott célplatform alapján.

Gyakori célplatform-makrók:

SzimbólumAktiválódás feltételeLapka példa
__AVR__Bármilyen AVR célplatformUNO, Nano, Mega
__AVR_ATmega328P__Csak akkor, ha ATmega328P van kiválasztvaUNO, Nano
__AVR_ATmega2560__Ha Mega2560-at céloz a fordításArduino Mega 2560
__AVR_ATtiny85__Ha ATTiny85-t céloz a fordításDigispark, Mini USB modul

Példa – platformhoz igazított funkció:

1
2
3
4
5
6
7
8
9
#ifdef __AVR_ATmega2560__
  #define LED_PIN 13
#elif defined(__AVR_ATmega328P__)
  #define LED_PIN 6
#else
  #define LED_PIN 1
#endif
 
pinMode(LED_PIN, OUTPUT);

Ez a struktúra lehetővé teszi, hogy ugyanaz a kód másképp viselkedjen különböző hardveren.

Az Arduino környezet által definiált szimbólumok

– avagy mit tud a fordítórendszer a választott lapkáról, mielőtt még egy sornyi kódot lefuttatna

IDE-verzió, architektúra és alaplap-változat – a platform nyomai

Az Arduino fejlesztőkörnyezet (IDE) nem pusztán szerkesztőfelület – komplett build-rendszer, amely egy előre meghatározott konfigurációs logika szerint állítja össze a fordítási környezetet. Ez a háttérben meghívott avr-gcc (vagy más architektúra-specifikus fordító) parancssorait a következő fájlok alapján állítja össze:

  • platform.txt
  • boards.txt
  • build flags sablonok

Ezekből automatikusan létrejönnek olyan szimbólumok, mint:

SzimbólumForrásÉrték vagy állapot
ARDUINOIDE verzió (build.core)pl. 10819 a 1.8.19 esetén
ARDUINO_AVR_UNOboards.txt lapnév-szimbólumdefined() ha UNO van kiválasztva
ARDUINO_ARCH_AVRplatform.txt architektúramindig jelen van az AVR platformon

Technikai háttér:
Az IDE a platform beállításait feldolgozva -D kapcsolókkal látja el a fordítót, pl.:

1
-DARDUINO=10819 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR

Ezek mindegyike #define-ként hat a forráskódra, így a #ifdef ARDUINO_AVR_UNO típusú feltételek azonnal működnek.

Órajel (F_CPU) – a rejtett időzítő

Az egyik legfontosabb környezeti szimbólum az F_CPU, amely megmondja, milyen frekvenciával fut a mikrokontroller. Ennek értéke Hz-ben van, például 16000000UL, vagy 8 MHz-es lapkáknál 8000000UL.

Nem deklarálni kell – az IDE beírja helyetted. A platform.txt-ből származik, pl.:

1
2
build.f_cpu=16000000L
 

Fordításkor a parancssor így néz ki:

1
-D F_CPU=16000000UL

A F_CPU hatással van az időalapú függvények működésére – tipikus példája a mikrokontroller órajel szimbólum F_CPU értelmezése, pl. delay(), millis(), micros().

Példa – különbség 8 MHz vs 16 MHz esetén:

1
2
3
4
5
#if F_CPU < 10000000UL
  Serial.println("Lassabb lapka (pl. 8 MHz)");
#else
  Serial.println("Gyorsabb lapka (pl. 16 MHz)");
#endif

Ha a F_CPU nincs jól definiálva, időzítési hibák léphetnek fel (pl. kétszer olyan hosszú delay()).

USB és hardver-specifikus azonosítók

Modern Arduino lapok – pl. Leonardo, Micro vagy STM32-alapú lapok – USB kapcsolatot is biztosítanak, amihez további beépített szimbólumok kapcsolódnak:

SzimbólumJelentésPélda
USB_VIDUSB vendor ID0x2341 az Arduino SA-hoz
USB_PIDUSB product IDtípusfüggő, pl. 0x0043
ARDUINO_USB_MODEMód: eszköz, host, dual1, 2 stb. típustól függően

Ezek jellemzően a core könyvtár és a boards.txt meghatározása alapján kerülnek be. Segítenek például különbséget tenni:

  • USB-CDC vagy HID típusú kapcsolat
  • Programozható USB-eszköz azonosító beállítás

Könyvtárbeállítások és IDE-fázis szimbólumok

Amikor egy könyvtár betöltődik, nem minden függvény aktív. A rendszer szakaszokra bontja a fordítást, és bizonyos szimbólumok csak bizonyos fázisokban élnek.

Példák:

  • ARDUINO_LIB_DISCOVERY_PHASE: csak a könyvtárlista építésekor van jelen
  • ARDUINO_BUILD_CORE: core build közben aktív (újabb build rendszerben)

Ezek ritkán használtak, de könyvtár- vagy board-definíció írásakor elengedhetetlenek.

Használatuk kockázatai

1. Dokumentálatlanság: Ezek a szimbólumok nem mindig szerepelnek hivatalos dokumentációban. Gyakran csak boards.txt, platform.txt fájlokból derülnek ki.
2. IDE-verziófüggés: Az ARDUINO vagy ARDUINO_ARCH_... szimbólum más lehet újabb/alternatív IDE-kben (pl. Arduino CLI, PlatformIO).
3. Túlzott szétágaztatás: Ha túl sok #ifdef, #elif, #else van a kódban, nehéz követni és karbantartani.

Egy írógép és egy laptop képernyőjén is C-preprocesszor direktívák láthatók, egy műhelyasztalon elhelyezve.
Régi és új: kódgenerálás időutazása.

Hol és hogyan találhatók meg ezek a szimbólumok?

Láthatatlan, de nem elérhetetlen – a makrók felfedése

Ezeket a szimbólumokat a fordító a háttérben automatikusan beilleszti, de nem mindig dokumentálja. Ha tudni szeretnéd, milyen #define-ek élnek egy adott környezetben, több lehetőség is van:

1. Kódon belüli ellenőrzés – fejlesztői trükkök

A) #warning direktíva – figyelmeztetés fordításkor

Könnyen kiírhatsz üzenetet a fordítási folyamat során:

1
2
3
#ifdef __AVR_ATmega328P__
#warning "ATmega328P célplatform aktív"
#endif

Ez nem futásidőben jelenik meg, hanem a fordítási kimenetben – tipikus példa a debug log készítése Arduino __FILE__ és __LINE__ segítségével.

B) #pragma message – egy alternatív út

Nem minden GCC-verzió támogatja, de ha igen, ez szöveget küld a buildlogba:

1
#pragma message("Build információ: Arduino UNO, 16MHz")

C) Szimbólumvizsgálat #ifdef-ekkel

Egyes szimbólumokat így tesztelhetsz:

1
2
3
4
5
6
#if defined(F_CPU)
  Serial.print("Órajel: ");
  Serial.println(F_CPU);
#else
  Serial.println("F_CPU nem definiált!");
#endif

Ez futásidőben ad visszajelzést, de a feltétel a fordítás során dől el.

2. IDE és buildrendszer: honnan jönnek ezek?

Arduino IDE az alábbi helyekről veszi a szimbólumokat:

  • hardware/arduino/avr/boards.txt
  • hardware/arduino/avr/platform.txt
  • automatikusan generált build flags (-D kapcsolók)

Példarészlet:

1
2
uno.build.board=AVR_UNO
uno.build.f_cpu=16000000L

Ebből lesznek:

1
-DARDUINO_AVR_UNO -DF_CPU=16000000UL

Arduino CLI és PlatformIO is hasonlóan működik – akár build_flags mezőkkel bővíthetőek.

Javasolt fejlesztési gyakorlat

Gyakorlat Miért hasznos?
Dokumentáld, mit használ a kód!A README.md vagy fejlécfájlban sorold fel
Csoportosítsd a makrókatEgységes #ifdef blokkokat használj
Használj saját #define-eketNe függj kizárólag az IDE szimbólumaitól
Teszteld több célra fordítvaVálts alaplapot, és figyeld a viselkedést

Mire jó mindez?

– a beépített szimbólumok mint fejlesztői munkaeszközök

A preproceszor makrói nem dekorációk. Nem azért vannak, hogy látványos legyen tőlük a kód – hanem hogy kézre álljon a fejlesztés, gyorsabban hibát találjunk, kevesebbet írjunk újra, jobban alkalmazkodjunk a hardverhez. Nézzük meg, milyen célokra használhatók igazán hatékonyan!

Hibakeresés, naplózás, visszajátszható kódverziók

Az Arduino világában gyakori, hogy egy kód több hónap után újra előkerül – és ilyenkor az első kérdés: „Ez melyik verzió is volt?”
Ha beépíted a build időpontját (__DATE__, __TIME__) vagy fájl- és sorazonosítót (__FILE__, __LINE__) a programba, az önmagát dokumentáló kóddá válik.

Életszerű helyzet:

Egy terepen használt szenzoregység furcsán viselkedik. Az eszköz nem csatlakoztatható számítógéphez, de van egy LCD kijelzője vagy soros logja. Ha kiírja, mikor fordult a firmware, máris tudod, hogy a régi 1.6.5 verzió fut-e rajta, vagy a legfrissebb.

Kód:

1
2
3
4
Serial.print("Build: ");
Serial.print(__DATE__);
Serial.print(" ");
Serial.println(__TIME__); // Arduino buildidő beágyazása programba

Fejlettebb:

1
#define DEBUG(msg) Serial.print(__FILE__); Serial.print(":"); Serial.print(__LINE__); Serial.print(" > "); Serial.println(msg)

Testreszabott kód különböző hardverekre

Az Arduino világban természetes, hogy ugyanazt a programot UNO-n, MEGA-n, NANO-n vagy ATTiny-n szeretnénk futtatni. A beépített szimbólumok ezt támogatják – a fordítás idején dönti el a rendszer, milyen hardverre épít, és így azt is, mit vegyen figyelembe.

Példa – külön I/O port más-más mikrokontrolleren:

1
2
3
4
5
6
7
#ifdef __AVR_ATmega328P__
  #define TEMP_SENSOR_PIN A0
#elif defined(__AVR_ATmega2560__)
  #define TEMP_SENSOR_PIN A12
#else
  #define TEMP_SENSOR_PIN A3
#endif

Ezután analogRead(TEMP_SENSOR_PIN) minden platformon jól működik – egy kóddal, három viselkedéssel.

Platform- és verzióspecifikus optimalizálás

Nem mindegy, milyen GCC-verzióval fordítunk. Bizonyos utasításkészletek, figyelmeztetések vagy optimalizálások csak újabb fordítóverziókban érhetők el.

Példa – eltérő elágazás GCC-verzió szerint:

1
2
3
4
5
#if __GNUC__ >= 8
  Serial.println("GCC 8 vagy újabb: használható újabb szintaxis");
#else
  Serial.println("Régebbi GCC: klasszikus módszert használunk");
#endif

Ez különösen fontos, ha könyvtárat fejlesztesz, és biztosítani szeretnéd a kompatibilitást.

Automatikus dokumentáció – a firmware saját magát azonosítja

Nagyon hasznos, ha a program képes „önmagáról beszélni”. A következő funkció ezt biztosítja:

Kód:

1
2
3
4
5
6
7
8
void printFirmwareInfo() {
  Serial.println("Firmware információ:");
  Serial.print("Forrás: "); Serial.println(__FILE__);
  Serial.print("Sor: "); Serial.println(__LINE__);
  Serial.print("Verzió: "); Serial.println(ARDUINO);
  Serial.print("Build: "); Serial.print(__DATE__); Serial.print(" "); Serial.println(__TIME__);
  Serial.print("Órajel: "); Serial.print(F_CPU); Serial.println(" Hz");
}

Hívás:

1
2
3
4
void setup() {
  Serial.begin(9600);
  printFirmwareInfo();
}

Feltételes hibakezelés és biztonságosabb build

A #error direktíva lehetőséget ad, hogy fordítási hibát generálj, ha valami fontos hiányzik:

1
2
3
#ifndef F_CPU
  #error "Az órajel nincs definiálva. Kérlek, válassz alaplapot!"
#endif

Ez egy tudatos hibát okoz – de jobb most megállni, mint a terepen szembesülni azzal, hogy a delay() duplán vagy fele olyan gyorsan működik.

Hatékony kód újrafelhasználás – egyetlen forrás, sok célra

Ha könyvtárat, driver-t vagy példaprogramot írsz, gyakran kell egyazon kódot többféle lapkára testreszabni – tipikus esete a feltételes fordítás Arduino AVR környezetben. A #ifdef __AVR__ típusú vizsgálatokkal anélkül támogatod több célplatformot, hogy külön fájlokat kellene karbantartanod.

Technikai szerkezet:

1
2
3
4
5
6
7
#if defined(__AVR__)
  // AVR-specifikus rész
#elif defined(ESP32)
  // ESP32-specifikus rész
#else
  // univerzális tartalék megoldás
#endif

Kitekintés – a preproceszor határai és öröksége

– amikor a kód nemcsak fut, hanem szerkeszti is önmagát

Történeti háttér – honnan jött a preproceszor?

A C nyelvet az 1970-es évek elején fejlesztette ki Dennis Ritchie a Bell Labsban. A C előfeldolgozóját (preproceszorát) eredetileg azért hozták létre, hogy:

  • Külön fájlokból lehessen beolvasni definíciókat (#include)
  • Nevekhez (pl. PIN számok) lehessen értéket rendelni (#define)
  • A kódot lehessen platform szerint igazítani (#ifdef)

Ez a megközelítés különösen erőssé vált a beágyazott rendszerek világában, ahol egyazon programot többféle hardverre kellett lefordítani. Így vált a preproceszor a C nyelv egyik legismertebb és legkarakteresebb alkotórészévé.

Hogyan működik pontosan a preproceszor?

Mielőtt a fordító (compiler) valóban értelmezné a C vagy C++ kódot, egy szövegszintű átírási folyamat megy végbe – ezt végzi a preproceszor. A #define, #ifdef, #include, #pragma, #error és társaik mind ebbe a rétegbe tartoznak.

  • Nem futásidőben dolgozik, hanem még a fordítás előtt
  • A #define szabályok szerint kicseréli az azonosítókat konkrét értékekre
  • A #ifdef típusú vizsgálatok hatására akár egész kódrészek nem kerülnek be a programba

Például:

1
2
3
4
#define PI 3.14159
 
float r = 2;
float c = 2 * PI * r;

A fordító valójában ezt látja:

1
2
float r = 2;
float c = 2 * 3.14159 * r;

Ezért mondjuk, hogy a preproceszor nem program, hanem egy szövegszintű átíró modul.

A metaprogramozás határán

Sokan a C/C++ preproceszort a metaprogramozás egy kezdetleges formájának tartják – olyan programozásnak, amelyben a kód önmagát módosítja. Ez nem teljesen alaptalan:

  • A kód szerkezete a fordítás során változik
  • A viselkedés platformhoz, verzióhoz, környezethez igazodik
  • Nincs „tudata” – csak szövegként cserél, mégis erőteljes

Azonban a lehetőségei korlátozottak. Nem tudsz például for ciklust írni benne, nem tudsz szimbólumokat „lekérdezni”, csak ha explicit definiáltad őket.

Más nyelvek hogyan oldják meg?

A modern programnyelvek – mint a Rust, Go, Python vagy Java – teljesen száműzték a preproceszort. Ehelyett:

  • Modulrendszerekkel oldják meg a #include helyett a komponensek beemelését
  • A feltételes működést if ... else struktúrák, osztályhierarchiák vagy függvénydekorátorok kezelik
  • A build rendszer (pl. cargo, gradle, pip) szabályozza, milyen platformra mi fordul

A C és C++ ezzel szemben megtartotta a preproceszort – részben visszafelé kompatibilitás, részben teljesítmény okán.

Hol a határ? Mikor NE használjuk?

A beépített szimbólumok és makrók csábítóak – de nem helyettesítik a jó programtervet. Ha túl sok #ifdef van egy fájlban, az olvashatatlanná és nehezen karbantarthatóvá válik.

Ajánlás:

  • Ha háromnál több hardvertípust támogatnál: bontsd fájlokra (pl. platform_uno.h, platform_mega.h)
  • Ha verziók szerint ágazik a logika: inkább const értékek, enumok
  • Ha a logika futásidőben változik: ne próbáld meg fordítási időben kitalálni
Egy nyitott könyvből bináris kód áramlik egy lebegő Arduino panel felé, C-preprocesszor direktívák mellett. Arduno kód valamint a preprocesszor és a __DATE__
Tudásból technológia: a könyv, amelyből kód születik.

A nagy mintakód

Beépített makrók feltérképezése – amit az IDE elhallgat

Nem minden az, amit leírsz. Amikor egy Arduino programot fordítasz, a háttérben a rendszer kiegészíti a kódot olyan sorokkal, amik nincsenek a sketch-ben – ezek a rejtett makrók. A következő kis kódrészlet soros portra írja ki azokat a beépített szimbólumokat, amelyek ténylegesen aktívak a fordítási környezetedben. De mire jó ez?

  • Ha tudni akarod, milyen lapra fordítasz éppen
  • Ha különböző platformokhoz írsz univerzális kódot
  • Ha pontos build-információt akarsz naplózni

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
void setup() {
  Serial.begin(115200);
  while (!Serial); // Várjuk meg a kapcsolatot (pl. Leonardo-nál)
 
  Serial.println(F("Elérhető makrók a fordítási környezetben:"));
  Serial.println(F("=========================================="));
 
  // Build információk
  Serial.print(F("Fájl neve: ")); Serial.println(__FILE__);
  Serial.print(F("Fordítás ideje: ")); Serial.print(__DATE__); Serial.print(" "); Serial.println(__TIME__);
 
  // Fordító verzió
#ifdef __GNUC__
  Serial.print(F("GCC főverzió: ")); Serial.println(__GNUC__);
  Serial.print(F("GCC minor: ")); Serial.println(__GNUC_MINOR__);
  Serial.print(F("GCC patch: ")); Serial.println(__GNUC_PATCHLEVEL__);
#endif
 
  // Nyelvi infók
#ifdef __cplusplus
  Serial.print(F("C++ nyelvi szint: ")); Serial.println(__cplusplus);
#endif
 
#ifdef __STDC__
  Serial.println(F("Standard C támogatás: Igen"));
#endif
 
  // Platform-specifikus
#ifdef __AVR__
  Serial.println(F("Célplatform: AVR"));
#endif
 
#ifdef __arm__
  Serial.println(F("Célplatform: ARM"));
#endif
 
#ifdef __SAM__
  Serial.println(F("Célplatform: SAM (pl. Due)"));
#endif
 
#ifdef F_CPU
  Serial.print(F("Órajel (F_CPU): ")); Serial.print(F_CPU); Serial.println(F(" Hz"));
#else
  Serial.println(F("F_CPU nincs definiálva"));
#endif
 
#ifdef ARDUINO
  Serial.print(F("Arduino IDE verzió: ")); Serial.println(ARDUINO);
#endif
 
#ifdef ARDUINO_ARCH_AVR
  Serial.println(F("Architektúra: AVR"));
#endif
 
#ifdef ARDUINO_AVR_UNO
  Serial.println(F("Alaplap: Arduino UNO"));
#endif
 
#ifdef USB_VID
  Serial.print(F("USB Vendor ID: ")); Serial.println(USB_VID, HEX);
#endif
 
#ifdef USB_PID
  Serial.print(F("USB Product ID: ")); Serial.println(USB_PID, HEX);
#endif
 
  Serial.println(F("=========================================="));
  Serial.println();
}
 
void loop() {
  // Itt nincs dolgunk – egyszeri kiíratás történik a setup()-ban
}

De mire figyelj ha hazsnálod a makrókat?

  • A makrók fordítási időben léteznek – a mikrokontrollerben már nem látszanak.
  • Ha a F_CPU nem szerepel a listában: valami nincs jól beállítva a board configban.
  • A ARDUINO, ARDUINO_ARCH_AVR, ARDUINO_AVR_UNO stb. automatikusan jönnek az IDE-ből – nem kell definiálnod.
  • Ezek a szimbólumok jól jönnek például #ifdef-es elágazásokhoz, hogy egy kód több platformon is fusson.

Ez a kis kód tökéletes kiindulópont, ha meg akarod tudni, milyen környezetet lát a fordító. Beágyazott rendszereknél – pláne, ha többféle lapkát és fordítót használsz – szinte kötelező eszköz a tarsolyban!

Zárás – Neked van kedvenc szimbólumod?

A programozás – különösen az Arduino-féle mikrokontrolleres világban – nem csupán parancsok írása a megfelelő sorrendben. Sokkal inkább rendszerben való gondolkodás, időben és térben. A fordító által biztosított beépített szimbólumok ezt a rendszert teszik láthatóvá.

Ezek a __DATE__, F_CPU, ARDUINO_AVR_UNO típusú rejtett segítők nem titokzatos képességek – de pont olyanok, mint a jó villanyszerelő szerszámai: akkor hiányoznak, amikor már baj van. Hibakereséshez, optimalizáláshoz, új platformokra való átálláshoz nélkülözhetetlenek.

Ha ismered őket, nemcsak rövidebb és tisztább kódot írsz – hanem stabilabb, időtállóbb és újrahasznosíthatóbb megoldásokat építesz.

Te mit gondolsz?

Találkoztál már olyan projekttel, ahol egy beépített szimbólum mentette meg a napot?
Esetleg volt olyan, amelyet nehezen értettél meg a #ifdef rengeteg miatt?
Van saját trükköd a __LINE__ vagy a F_CPU kihasználására?

Írd meg kommentben vagy oszd meg a tapasztalatod a közösséggel!

 

Felhasznált források

  • Arduino hivatalos oktatási anyagai [arduino.cc]
  • Sketch build process – Arduino Documentation [arduino.cc]
  • Understanding the Arduino Sketch Build Process [circuits.rock]
  • Conditional Compilation – Quantum Leaps [state-machine]
  • #if, #elif, #else, and #endif directives (C/C++) [Microsoft]
  • What happens in Arduino IDE when we click Compile? [Medium]
  • Challenges of Embedded Firmware Development and Common Solutions [Integrasources]
  • Rendszerezett Arduino programozás – avagy hogyan győztem le a spagettikódot [TavIR]

Post navigation

Előző Kétszínű LED modul kapcsolása Arduino UNO-hoz (KY-029)
Következő NTC hőmérő modul tesztelése Arduino-val – stabil analóg mérés alapjai (KY-013)

Kapcsolódó anyagok

A digitális idő paradoxonja: az óraátállítás árnyoldalai Ködös kertben analóg és digitális óra, köztük egy végtelen jelet formázó fényív, alatta automata locsoló rendszer – az őszi óraátállítás kettőzött időpontját szimbolizálva.
  • Cikk
  • Mélyvíz
  • Tippek

A digitális idő paradoxonja: az óraátállítás árnyoldalai

2025.10.23.
Teker Ed, te tekered? – Az enkóder Illusztrált forgó enkóder modul Arduino fejlesztőkörnyezetben, számítógéppel és elektronikai munkapaddal. Oktatási és DIY elektronikai célokra.
  • Cikk
  • Gyorstippek

Teker Ed, te tekered? – Az enkóder

2025.08.23.
DS1302 trükkök: RAM, írásvédelem, burst mód és csepptöltés (trickle charge) DS1302 RTC modul egy Arduino fejlesztőasztalon, háttérben laptop és prototípus panelek – Arduino DS1302 valós idejű óra interfész bemutató.
  • Cikk
  • Gyorstippek

DS1302 trükkök: RAM, írásvédelem, burst mód és csepptöltés (trickle charge)

2025.08.20.

Hírlevél

Hogy az újdonságokról első kézből értesülj:
→ Feliratkozás a Hírlevélre

Ingyenes tanfolyam

60 nap alatt Arduino - az ingyenes tanfolyam
→ Kattints ide és iratkozz fel!
60 nap alatt Arduino

Szeretnél egy lépéssel a többiek előtt járni?

Ne hagyd ki a legújabb tanfolyamokat, amik még csak most bontogatják szárnyaikat.

Legyél te az első! Tanfolyamok

Alkatrész-tár

→ TavIR WebShop
→ Tanulókészletek

Témakörök

  • Cikk (49)
  • Hír (35)
  • Könyv (34)
    • Egyszerű elektronika tippek (18)
    • ESP8266/ESP32 (1)
    • Mélyvíz (8)
    • Mit ne használjunk Arduino projektekben? (6)
  • Tippek (59)
    • Gyorstippek (20)
    • Tippek-trükkök (AVR) (21)
    • Tippek-trükkök (ESP8266/ESP32) (5)

TavIR WebShop

→ Tovább a TavIR WebShopba
4 csatornás kétirányú jelszintillesztő modul (digitális vonalakhoz, MOSFET)
4 csatornás kétirányú jelszintillesztő modul (digitális vonalakhoz, MOSFET)

Univerzális, 4 csatornás kétirányú jelszintillesztő modul, amely megbízható módon biztosítja a digitális [...]

Mérleg súlymérő cella (500g)
Mérleg súlymérő cella (500g)

A 500 g-os mérleg súlymérő cella egy kis méretű, mégis meglepően pontos terhelésérzékelő, [...]

USB-A - USB-A galvanikus leválasztó (1500V, isolátor, USB 2.0 izolátor, hi-speed/480Mbps)
USB-A - USB-A galvanikus leválasztó (1500V, isolátor, USB 2.0 izolátor, hi-speed/480Mbps)

Az USB-A - USB-A leválasztó a PC védelmét szolgálja, a statikus kisülés [...]

Arduino UNO R4 WiFi (ABX00087) - az eredeti, fejlett Wi‑Fi és Bluetooth funkcionalitású fejlesztőpanel
Arduino UNO R4 WiFi (ABX00087) - az eredeti, fejlett Wi‑Fi és Bluetooth funkcionalitású fejlesztőpanel

Az Arduino UNO R4 WiFi (ABX00087) egy 32‑bites fejlesztőpanel, amely beépített Wi‑Fi és Bluetooth modullal [...]

XKC‑Y25‑T12V érintésmentes folyadékszint‑érzékelő modul, kapacitív működéssel (5–12 V DC)
XKC‑Y25‑T12V érintésmentes folyadékszint‑érzékelő modul, kapacitív működéssel (5–12 V DC)

Az XKC‑Y25‑T12V egy érintkezés nélküli, kapacitív elven működő folyadékszint‑érzékelő, mely ideális zárt, [...]

LiPo akku (902040, 3.7V, 1000mAh)
LiPo akku (902040, 3.7V, 1000mAh)

Ez a 902040 típusú lítium-polimer (LiPo) akkumulátor kompakt megoldást kínál olyan hordozható [...]

12V digitális termosztát modul - beépíthető, tokos kivitelű hőmérséklet-szabályozó (W1209WK/W1209)
12V digitális termosztát modul - beépíthető, tokos kivitelű hőmérséklet-szabályozó (W1209WK/W1209)

A W1209WK digitális termosztát egy kompakt, intelligens hőmérséklet-szabályozó modul 12 V DC [...]

VEML6040 I2C RGBW színmérő modul (IIC)
VEML6040 I2C RGBW színmérő modul (IIC)

A VEML6040 I2C RGBW színmérő modul egy nagy pontosságú, négysávos (R–G–B–W) fényérzékelő, [...]

Elektromágneses lövedék gyorsító (DIY Coil Gun) készlet – Electromagnetic Gun DIY Kit
Elektromágneses lövedék gyorsító (DIY Coil Gun) készlet – Electromagnetic Gun DIY Kit

Ez az Elektromágneses lövedék-gyorsító DIY Készlet (más néven coil gun kit) olyan [...]

USB-A - USB-A galvanikus leválasztó (CH318T, 1500V, USB 2.0 izolátor, full speed (480Mbps), 400mA)
USB-A - USB-A galvanikus leválasztó (CH318T, 1500V, USB 2.0 izolátor, full speed (480Mbps), 400mA)

A CH318T alapú USB 2.0 nagysebességű galvanikus leválasztó modul célja, hogy biztonságos [...]

Akril tok ESP32‑S3 4,3 hüvelykes 800×480 kijelzős fejlesztőpanelhez – LVGL HMI kompatibilis
Akril tok ESP32‑S3 4,3 hüvelykes 800×480 kijelzős fejlesztőpanelhez – LVGL HMI kompatibilis

Ez az akrilház (plexi tok) kifejezetten az ESP32‑S3 alapú, 4,3 hüvelykes, 800×480 [...]

LM35D / LM35DZ lineáris, analóghőmérséklet‑érzékelő modul
LM35D / LM35DZ lineáris, analóghőmérséklet‑érzékelő modul

Ez az LM35D / LM35DZ típusra épülő hőmérséklet‑érzékelő modul egyszerű, megbízható és [...]

Fórum

  • Ami máshova nem besorolható... :: Re: Melyik humanoid robot gyártó lesz a piacvezető 2030-ban?
  • Ami máshova nem besorolható... :: Melyik humanoid robot gyártó lesz a piacvezető 2030-ban?
  • Bascom-AVR nyelvű programozás (AVR programozásának lehetőségei) :: Re: DC servo motor szabalyzo
  • Tovább a TavIR Fórumra...

Címkék

alappanel Arduino Arduino nap Arduino nap 2023 art atmel AVR billentyűzet biztosíték darlington dióda eeprom egyszerű elektronika elem ellenállás ESP Espressif Systems flash Forrasztás ft232 fusebit hang hőmérő i2c i2clcd infravörös ISP JTAG kijelző LCD lm35 megvilágítás microchip MOSFET motor pcb páratartalom Relé RTC telepítés tmp36 tranzisztor Uno Zener óra

Archívum

  • 2025. október (3)
  • 2025. augusztus (3)
  • 2025. július (7)
  • 2025. június (4)
  • 2025. május (6)
  • 2025. április (5)
  • 2025. március (4)
  • 2025. február (1)
  • 2025. január (6)
  • 2024. december (5)
  • 2024. november (5)
  • 2024. október (6)
  • 2024. szeptember (5)
  • 2024. augusztus (4)
  • 2024. július (3)
  • 2024. június (1)
  • 2024. május (3)
  • 2024. március (1)
  • 2024. február (2)
  • 2024. január (1)
  • 2023. december (3)
  • 2023. szeptember (2)
  • 2023. augusztus (6)
  • 2023. július (2)
  • 2023. június (1)
  • 2023. május (1)
  • 2023. április (10)
  • 2023. február (1)
  • 2022. szeptember (2)
  • 2022. július (1)
  • 2022. május (6)
  • 2022. április (1)
  • 2022. március (2)
  • 2022. január (2)
  • 2021. december (1)
  • 2021. november (4)
  • 2021. október (2)
  • 2021. szeptember (1)
  • 2021. július (1)
  • 2021. május (2)
  • 2021. április (1)
  • 2021. március (2)
  • 2020. szeptember (1)

Eddig nem olvasott...

A digitális idő paradoxonja: az óraátállítás árnyoldalai Ködös kertben analóg és digitális óra, köztük egy végtelen jelet formázó fényív, alatta automata locsoló rendszer – az őszi óraátállítás kettőzött időpontját szimbolizálva.
  • Cikk
  • Mélyvíz
  • Tippek

A digitális idő paradoxonja: az óraátállítás árnyoldalai

2025.10.23.
Qualcomm-Arduino: amikor a nyílt hardver találkozik az ipari óriással Közelkép egy Arduino UNO Q mikrokontroller panelről, amelyen jól látható a Qualcomm Dragonwing logó és a nyomtatott áramkörök részletei. AI-alapú beágyazott rendszerekhez és prototípusfejlesztéshez ideális.
  • Hír

Qualcomm-Arduino: amikor a nyílt hardver találkozik az ipari óriással

2025.10.08.
Arduino UNO Q – Az új korszak kezdete: Linux és valós idejű vezérlés egy lapon Egy futurisztikus megvilágítású Arduino UNO Q fejlesztőlap, középpontban egy Qualcomm QRB2210 chip, kék alaplapon mikrokontrolleres és IoT-alkalmazásokhoz optimalizált alkatrészekkel. AI és IoT fejlesztésekhez készült hardver.
  • Hír

Arduino UNO Q – Az új korszak kezdete: Linux és valós idejű vezérlés egy lapon

2025.10.07.
Teker Ed, te tekered? – Az enkóder Illusztrált forgó enkóder modul Arduino fejlesztőkörnyezetben, számítógéppel és elektronikai munkapaddal. Oktatási és DIY elektronikai célokra.
  • Cikk
  • Gyorstippek

Teker Ed, te tekered? – Az enkóder

2025.08.23.

Információk

Cégadatok-impresszum | Használati feltételek
Adatvédelmi irányelvek | Kapcsolat

Elérhetőség

Ügyfélszolgálat: +36 (20) 99-23-781
E-mail: avr (kukac)tavir (pont) hu
Iroda/telephely: 1181 Budapest, Szélmalom utca 13.
Copyright © TavIR Minden jog fenntartva | DarkNews by AF themes.
TavIR
Manage your privacy

To provide the best experiences, we and our partners use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us and our partners to process personal data such as browsing behavior or unique IDs on this site and show (non-) personalized ads. Not consenting or withdrawing consent, may adversely affect certain features and functions.

Click below to consent to the above or make granular choices. Your choices will be applied to this site only. You can change your settings at any time, including withdrawing your consent, by using the toggles on the Cookie Policy, or by clicking on the manage consent button at the bottom of the screen.

Funkcionális Always active
A technikai tárolás vagy hozzáférés szigorúan szükséges az előfizető vagy felhasználó által kifejezetten kért konkrét szolgáltatás használatának lehetővé tételének jogos céljához, vagy kizárólag a közlés elektronikus hírközlő hálózaton keresztüli továbbításának céljához.
Beállítások
A technikai tárolás vagy hozzáférés a jogos célból szükséges, hogy olyan beállításokat tároljunk, amelyeket az előfizető vagy a felhasználó nem kért.
Statisztika
Kizárólag statisztikai célokra használt technikai tároló vagy hozzáférés. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
A technikai tárolás vagy hozzáférés felhasználói profilok létrehozásához szükséges hirdetések küldéséhez, illetve a felhasználó nyomon követéséhez egy vagy több weboldalon hasonló marketingcélokból.
Statistics

Marketing

Features
Always active

Always active
Manage options Manage services Manage {vendor_count} vendors Read more about these purposes
Manage options
{title} {title} {title}