Czy słyszałeś(-aś) o terminie "kompilacja warunkowa" 🤔? Działa bardzo podobnie jak zwykła instrukcja warunkowa z tą różnicą, że tłumaczy odpowiedni fragment kodu źródłowego w zależności od występowania konkretnej dyrektywy ✅. a jego wynik jest przetwarzany na etapie preprocesora! O tym, jak kompilacja warunkowa w języku C wygląda w praktyce i jak z tego korzystać, piszę w środku ✒️.

KOMPILACJA WARUNKOWA W JĘZYKU C. TWORZENIE ZALEŻNOŚCI NA POZIOMIE PREPROCESORA

Zacznijmy od przedstawienia przykładowego scenariusza. Wyobraźmy sobie prostą instrukcję "if", która posiada jakiś konkretny warunek, na przykład 👇:

if(x < 5)
{
	// instrukcje
}

W środku bloku zostaną wykonane jakieś polecenia. Zawsze będzie to uwzględnione przez kompilator i zawsze będzie występować w pliku wykonywalnym, niezależnie od tego, czy to się spełni, czy nie.

Mamy to 🙂?

To teraz wyobraź sobie, że kompilacja warunkowa w języku C, zamiast instrukcji warunkowej korzysta z dyrektywy, a instrukcje istnieją fizycznie w pliku wykonywalnym (po przetłumaczeniu na kod maszynowy) wtedy i tylko wtedy, gdy stała osadzona jako warunek (pochodząca z dyrektywy "#define") została zdefiniowana ℹ️:

#ifdef CONSTANT
// definicje innych stałych
#endif

Tym się różni jedno od drugiego 💡!

Do uwarunkowania bloków kodu zależnie od wskazanej stałej (utworzonej za pomocą "#define"), stosujemy 3 hasła:

  1. "#ifdef" - odpowiednik "if",
  2. "#else" - odpowiednik "else",
  3. "#endif" - oznaczenie końca bloku kompilacji warunkowej (tego wyjątkowo nie ma w instrukcji warunkowej 🙂).

Zatem:

  • instrukcja warunkowa jest osadzona na stałe w programie, a spełnialność jest sprawdzana w trakcie działania programu,
  • kompilacja warunkowa uzależnia osadzenie kodu w programie od występowania wskazanej dyrektywy, a spełnialność jest sprawdzana jeden raz przez preprocesor (podczas "sklejania" programu).

Czyli kompilacja warunkowa jest wykonywana tylko na początku i tylko jeden raz dochodzi do sprawdzenia warunków na etapie działania preprocesora. Instrukcja warunkowa jest w kodzie zawsze i może podlegać wielokrotnym testom (to już zależy od budowy programu) 🧨.

ZASTOSOWANIE

W pytaniu o użyteczność, kompilacja warunkowa w języku C bardzo się przydaje przy zapewnianiu przenośności kodu na wiele platform i systemów ℹ️. Na przykład jakiś projekt może być tworzony pierwotnie pod system Windows, a później, dzięki kompilacji warunkowej, "przeniesiony" na inne platformy ❤️. To pozwala na programowanie wieloplatformowych aplikacji poprzez adaptację obsługi i obchodzenie ograniczeń (bo np. na smartfonie nie masz myszki 😊), natomiast wciąż operujesz na tym samym projekcie - to jest bardzo istotne 🔥!

Potem wystarczy jedynie zmienić odpowiednie stałe dostosowane do odpowiedniej platformy, skompilować kod i tym sposobem uzyskać ten sam produkt, tylko dostosowany pod inną platformę. Dzięki kompilacji warunkowej, staje się możliwe tworzenie przenośnych programów na różne platformy, bez duplikowania kodów źródłowych ⭐!

Operacja przenoszenia znana jest również pod hasłem "portowanie" - jest ono powszechnie stosowane w branży gier (mojej ulubionej 🥰!).

PRZYKŁAD KODU ŹRÓDŁOWEGO

Pora to podsumować prostym kodem źródłowym na do widzenia 😄. Mamy program, który wypisuje odpowiednią treść komunikatu w zależności od zdefiniowanych stałych. Popatrz na niego 👇:

#include <stdio.h>

#ifdef _WIN32
#define MESSAGE "To jest system Windows.\n"
#else
#define MESSAGE "To nie jest system Windows.\n"
#endif

#define NUMBER_SHOULD_BE_EVEN

#ifdef NUMBER_SHOULD_BE_EVEN
#define NUMBER 2
#else
#define NUMBER 1
#endif

int main(void)
{
	printf(MESSAGE);
	printf("Liczba = %d\n", NUMBER);
	
	return 0;
}

U samej góry mamy sporo dyrektyw odpowiadających za kontrolę programu na etapie preprocesora. Dodałem 2 różne "typy": z użyciem stałej występującej w języku i z użyciem stałej niestandardowej.

UŻYCIE WBUDOWANEJ STAŁEJ

To:

#ifdef _WIN32

sprawdza czy system operacyjny, na jakim skompilujesz ten program, to system Windows 😊. To jest przykład wykorzystujący jedną z wbudowanych stałych. Dla poszczególnych systemów operacyjnych, obowiązują następujące stałe:

Windows = _WIN32
Mac = __APPLE__ lub __MACH__
Linux = __linux__

W zależności od tego, jaki masz system operacyjny, możesz sobie spróbować zamienić na wskazane stałe (nie miałem możliwości przetestować dla Maca i Linuxa, więc uprzedzam, że mogłem popełnić błąd ⚠️!).

Tak czy siak, w zależności od rozstrzygnięcia jaki to system, inna stała otrzyma inną wartość. A co za tym idzie, ujrzymy co innego w funkcji "printf" 💥!

UŻYCIE WŁASNEJ STAŁEJ

To z kolei:

#ifdef NUMBER_SHOULD_BE_EVEN

jest stała utworzona przeze mnie 😄. Zwróć uwagę, że nie musiałem podawać żadnej wartości!

#define NUMBER_SHOULD_BE_EVEN

Sprawdzamy czy istnieje taka stała zdefiniowana pod podaną nazwą. I znowu - jeżeli tak, to inna stała przyjmie inną wartość, a jeżeli nie, to inną ✔️.

W obu przypadkach, tylko ten jeden raz przed kompilacją, zostanie to zbadane 🚨.

Kompilacja warunkowa w języku C

Kompilacja warunkowa w języku C to sposób na tworzenie przenośnych aplikacji poprzez warunkowe kompilowanie wskazanych bloków kodu zależnie od występujących stałych przez dyrektywy.


Zakończyliśmy wspólnie wątek kompilacji warunkowej ❤️. Nie będzie to tak często stosowane jak funkcje, aczkolwiek warto znać ten temat, zwłaszcza gdy zaczniesz chcieć pisać programy na kilka różnych platform 🎮.

PODOBNE ARTYKUŁY