#define — to dyrektywa preprocesora, która po prostu zastępuje wszystkie wystąpienia identyfikatora na wartość przed kompilacją. Nie tworzy zmiennych, nie zna typów, nie sprawdza granic i nie szanuje zakresu widoczności.
const — to kwalifikator, który tworzy prawdziwą zmienną, ale zablokowaną do zapisu po inicjalizacji. Zmienna const ma typ, zakres widoczności, bierze udział w debugowaniu i może być bardziej bezpieczna. Takie zmienne są umieszczane w segmencie .rodata lub na stosie/w pamięci operacyjnej.
#define — dla prostych wartości skalarowych, które są potrzebne na etapie kompilacji, zwłaszcza do użycia w warunkach preprocesora lub rozmiarach tablic (#define SIZE 16).const — dla wartości, które trzeba bezpiecznie typować, debugować oraz bezpiecznie eksportować (w plikach nagłówkowych, między modułami).const.Przykład:
#define PI 3.14159 const double G = 9.81; int arr[PI]; // BŁĄD! PI nie jest całkowite int arr2[G]; // BŁĄD! G nie jest wartością czasu kompilacji
Pytanie: Czy działa const int a = 10; jako stała czasu kompilacji do tworzenia tablicy: int arr[a];?
Odpowiedź: Nie. W języku C const — to kwalifikator, ale zmienna jest tworzona i inicjowana w czasie wykonania, a nie w czasie kompilacji, dlatego rozmiar tablicy musi być literałem lub wyrażeniem znanym kompilatorowi. Użyj #define, albo enum { SIZE = 10 };.
Przykład błędu:
const int a = 5; int arr[a]; // W C89/90 nie zadziała (VLA pojawiły się w C99, ale nie wszędzie)
Historia
Na serwerze multimedialnym próbowano używać
const intdo określenia rozmiarów bufora, myśląc, że to "stała czasu kompilacji". Na jednym kompilatorze (GCC, C99) wszystko działało, ale w większości — błąd kompilacji (VLA nie są wspierane), pilnie przepisali na #define.
Historia
W kodzie zależnym od platformy określono ciąg przez
#define NAME "MyApp", używano w kilku miejscach i zapomniano o nawiasach. Po dodaniu do ciągu znaków bez wyraźnych nawiasów otrzymywano błędne wyniki, prowadzące do dziwnych błędów w logach.
Historia
W projekcie z kilkoma modułami określono stałą przez #define w dwóch miejscach z różnymi wartościami (copy-paste). Wynik — moduły działały z różnymi stałymi, a normalizacja danych, które naprawiono dopiero przy skrupulatnym debugowaniu.